自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

關(guān)于 Spring AOP 的原理分析!

開發(fā) 后端
通過本文的分析,我們將了解了 Spring AOP的基本概念、實(shí)現(xiàn)機(jī)制、核心組件以及如何在實(shí)際項(xiàng)目中應(yīng)用 AOP。

Spring AOP是 Spring框架中的一個重要模塊,它通過分離關(guān)注點(diǎn)來提高代碼的模塊化程度,AOP允許開發(fā)者在不改變業(yè)務(wù)邏輯的情況下,通過切面來增強(qiáng)或修改代碼的行為。本文我們將深入分析 Spring AOP的原理。

一、Spring AOP概述

什么是AOP?

AOP,全程 Aspect-Oriented Programming,中文翻譯為面向切面編程,它是一種編程范式,旨在通過將橫切關(guān)注點(diǎn)(如日志記錄、事務(wù)管理、權(quán)限控制等)分離出來,使得這些關(guān)注點(diǎn)可以獨(dú)立于業(yè)務(wù)邏輯進(jìn)行處理。AOP的核心概念包括:

  • 切面(Aspect):模塊化的關(guān)注點(diǎn),通常橫切多個對象。
  • 連接點(diǎn)(Join Point):程序執(zhí)行過程中的某個點(diǎn),比如方法調(diào)用或異常拋出。
  • 通知(Advice):在切面的某個特定的連接點(diǎn)上執(zhí)行的動作。
  • 切入點(diǎn)(Pointcut):匹配連接點(diǎn)的斷言。
  • 目標(biāo)對象(Target Object):被通知的對象。
  • 代理(Proxy):通知目標(biāo)對象后,創(chuàng)建的對象。
  • 織入(Weaving):將切面連接到其它應(yīng)用程序類型或?qū)ο笊?,并?chuàng)建一個通知對象。

二、Spring AOP的核心原理

1.AOP的實(shí)現(xiàn)機(jī)制

Spring AOP基于代理模式實(shí)現(xiàn),主要通過Proxy對象來替代目標(biāo)對象,并在Proxy對象的方法調(diào)用中插入切面邏輯。Spring AOP使用ProxyFactory和AdvisedSupport等類來管理和創(chuàng)建代理對象。代理又可以細(xì)分為:

  • JDK動態(tài)代理:基于接口的代理,目標(biāo)對象必須實(shí)現(xiàn)一個或多個接口。
  • CGLIB代理:基于子類的代理,適用于目標(biāo)對象沒有實(shí)現(xiàn)接口的情況。

2.AOP的核心組件

  • Advisor:包含切入點(diǎn)和通知的元數(shù)據(jù)。
  • Advice:定義切面在連接點(diǎn)上執(zhí)行的操作。
  • Pointcut:定義匹配連接點(diǎn)的規(guī)則。
  • AopProxy:負(fù)責(zé)創(chuàng)建代理實(shí)例,具體實(shí)現(xiàn)有JdkDynamicAopProxy和CglibAopProxy。

3.AOP的執(zhí)行流程

Spring AOP的執(zhí)行流程是理解其工作原理的關(guān)鍵,它通過在程序運(yùn)行時(shí)動態(tài)地將切面邏輯織入到目標(biāo)對象中,從而實(shí)現(xiàn)橫切關(guān)注點(diǎn)的分離。下面我們來詳細(xì)地分析 Spring AOP的執(zhí)行流程。

(1) 配置切面

AOP的執(zhí)行流程從配置切面開始,切面可以通過 XML配置文件或基于注解的方式進(jìn)行定義。配置切面時(shí),主要涉及以下幾個元素:

  • 切面類(Aspect):包含橫切邏輯的類,通常用@Aspect注解標(biāo)識。
  • 通知方法(Advice):定義在特定連接點(diǎn)上執(zhí)行的橫切邏輯。通知類型包括@Before、@After、@Around、@AfterReturning、@AfterThrowing等。
  • 切入點(diǎn)表達(dá)式(Pointcut Expression):用于匹配連接點(diǎn)的方法執(zhí)行點(diǎn),通常使用AspectJ的切入點(diǎn)表達(dá)式語法。

(2) 創(chuàng)建代理對象

在Spring容器啟動時(shí),Spring會掃描配置的切面類,并為每個目標(biāo)對象創(chuàng)建代理對象。代理對象負(fù)責(zé)在目標(biāo)方法執(zhí)行前后插入切面邏輯。Spring AOP使用兩種主要的代理方式:

  • JDK動態(tài)代理:適用于目標(biāo)對象實(shí)現(xiàn)了接口的情況,通過Java的反射機(jī)制創(chuàng)建代理對象。
  • CGLIB代理:適用于目標(biāo)對象沒有實(shí)現(xiàn)接口的情況,通過生成目標(biāo)類的子類來創(chuàng)建代理。

(3) 方法調(diào)用攔截

當(dāng)客戶端代碼調(diào)用目標(biāo)對象的方法時(shí),實(shí)際上是通過代理對象來進(jìn)行調(diào)用的。代理對象實(shí)現(xiàn)了與目標(biāo)對象相同的接口,因此客戶端代碼無需感知代理的存在。

  • 攔截方法調(diào)用:代理對象攔截對目標(biāo)方法的調(diào)用。對于JDK動態(tài)代理,這是通過實(shí)現(xiàn)InvocationHandler接口的invoke方法來實(shí)現(xiàn)的;對于CGLIB代理,這是通過生成子類并重寫方法來實(shí)現(xiàn)的。

(4) 執(zhí)行通知

在方法調(diào)用被攔截后,代理對象會根據(jù)切面配置執(zhí)行相應(yīng)的通知邏輯:

  • Before通知:在目標(biāo)方法執(zhí)行之前執(zhí)行。
  • After通知:在目標(biāo)方法執(zhí)行之后執(zhí)行,無論方法是否拋出異常。
  • Around通知:包圍目標(biāo)方法的執(zhí)行,可以在方法執(zhí)行前后進(jìn)行自定義邏輯,甚至可以決定是否執(zhí)行目標(biāo)方法。
  • AfterReturning通知:在目標(biāo)方法成功返回后執(zhí)行。
  • AfterThrowing通知:在目標(biāo)方法拋出異常后執(zhí)行。

(5) 執(zhí)行目標(biāo)方法

在執(zhí)行完Before或Around通知的前置邏輯后,代理對象會調(diào)用目標(biāo)對象的實(shí)際方法。目標(biāo)方法執(zhí)行完成后,代理對象會繼續(xù)執(zhí)行After、Around的后置邏輯、AfterReturning或AfterThrowing通知。

(6) 返回結(jié)果或拋出異常

代理對象在完成所有通知邏輯后,將目標(biāo)方法的返回結(jié)果返回給調(diào)用方。如果目標(biāo)方法拋出異常,代理對象也會處理異常并根據(jù)配置決定是否重新拋出或轉(zhuǎn)換異常。

(7) 結(jié)束

AOP的執(zhí)行流程在代理對象返回結(jié)果或拋出異常后結(jié)束,整個過程是透明的,調(diào)用方無需關(guān)心代理的存在,目標(biāo)對象的行為在運(yùn)行時(shí)被增強(qiáng)。

三、Spring AOP核心源碼分析

Spring AOP的源碼涉及到多個核心類和接口,包括ProxyFactory、AdvisedSupport、AopProxy、JdkDynamicAopProxy、CglibAopProxy等。下面,我們將對這些核心組件進(jìn)行詳細(xì)分析。

1.ProxyFactory

ProxyFactory是Spring AOP創(chuàng)建代理的核心工廠類。它負(fù)責(zé)根據(jù)配置創(chuàng)建合適的代理對象(JDK動態(tài)代理或CGLIB代理)。

public class ProxyFactory extends ProxyCreatorSupport {

    // 獲取代理對象
    public Object getProxy() {
        return createAopProxy().getProxy();
    }

    // 創(chuàng)建AopProxy對象
    protected AopProxy createAopProxy() {
        if (!this.isProxyTargetClass()) { // 是否強(qiáng)制使用CGLIB代理
            return new JdkDynamicAopProxy(this);
        }
        return new CglibAopProxy(this);
    }
}
  • getProxy():對外提供獲取代理對象的方法。
  • createAopProxy():根據(jù)ProxyTargetClass屬性判斷使用JDK動態(tài)代理還是CGLIB代理。

2.AdvisedSupport

AdvisedSupport是Spring AOP的配置類,持有AOP代理需要的各種配置,包括目標(biāo)對象、切面、通知等。

public class AdvisedSupport extends ProxyConfig implements Advised {

    private TargetSource targetSource;
    private List<Advisor> advisors = new ArrayList<>();
    private List<Class<?>> interfaces = new ArrayList<>();

    // 其他配置和方法
}
  • TargetSource:封裝了目標(biāo)對象。
  • advisors:存儲應(yīng)用于目標(biāo)對象的通知(Advice)和切入點(diǎn)(Pointcut)。
  • interfaces:代理對象需要實(shí)現(xiàn)的接口列表。

3.AopProxy接口

AopProxy是一個接口,定義了AOP代理對象的創(chuàng)建方法。

public interface AopProxy {
    Object getProxy();
    Object getProxy(ClassLoader classLoader);
}
  • getProxy():用于創(chuàng)建代理對象。
  • getProxy(ClassLoader classLoader):允許指定類加載器創(chuàng)建代理對象。

4.JdkDynamicAopProxy

JdkDynamicAopProxy實(shí)現(xiàn)了AopProxy接口,使用JDK動態(tài)代理為目標(biāo)對象創(chuàng)建代理。

public class JdkDynamicAopProxy implements AopProxy, InvocationHandler {

    private final AdvisedSupport advised;

    public JdkDynamicAopProxy(AdvisedSupport config) {
        this.advised = config;
    }

    @Override
    public Object getProxy() {
        return getProxy(Thread.currentThread().getContextClassLoader());
    }

    @Override
    public Object getProxy(ClassLoader classLoader) {
        return Proxy.newProxyInstance(classLoader, this.advised.getProxiedInterfaces(), this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, this.advised.getTargetClass());

        if (chain.isEmpty()) {
            return method.invoke(this.advised.getTargetSource().getTarget(), args);
        }

        MethodInvocation invocation = new ReflectiveMethodInvocation(proxy, this.advised.getTargetSource().getTarget(), method, args, chain);
        return invocation.proceed();
    }
}
  • getProxy():通過Proxy.newProxyInstance創(chuàng)建代理對象。
  • invoke():實(shí)現(xiàn)InvocationHandler接口的方法,負(fù)責(zé)方法調(diào)用的攔截和通知鏈的執(zhí)行。

5.CglibAopProxy

CglibAopProxy同樣實(shí)現(xiàn)了AopProxy接口,使用CGLIB庫為目標(biāo)對象創(chuàng)建代理。

public class CglibAopProxy implements AopProxy {

    private final AdvisedSupport advised;

    public CglibAopProxy(AdvisedSupport config) {
        this.advised = config;
    }

    @Override
    public Object getProxy() {
        return getProxy(Thread.currentThread().getContextClassLoader());
    }

    @Override
    public Object getProxy(ClassLoader classLoader) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(this.advised.getTargetClass());
        enhancer.setInterfaces(this.advised.getProxiedInterfaces());
        enhancer.setCallback(new DynamicAdvisedInterceptor(this.advised));
        return enhancer.create();
    }

    private static class DynamicAdvisedInterceptor implements MethodInterceptor {

        private final AdvisedSupport advised;

        public DynamicAdvisedInterceptor(AdvisedSupport advised) {
            this.advised = advised;
        }

        @Override
        public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
            List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, this.advised.getTargetClass());

            if (chain.isEmpty()) {
                return proxy.invokeSuper(obj, args);
            }

            MethodInvocation invocation = new CglibMethodInvocation(obj, this.advised.getTargetSource().getTarget(), method, args, proxy, chain);
            return invocation.proceed();
        }
    }
}
  • getProxy():使用CGLIB的Enhancer創(chuàng)建代理對象。
  • DynamicAdvisedInterceptor:CGLIB的攔截器實(shí)現(xiàn),負(fù)責(zé)方法調(diào)用的攔截和通知鏈的執(zhí)行。

6.MethodInvocation

MethodInvocation接口及其實(shí)現(xiàn)類(如ReflectiveMethodInvocation)負(fù)責(zé)封裝方法調(diào)用的上下文信息,并管理通知鏈的執(zhí)行。

public interface MethodInvocation extends Joinpoint {
    Method getMethod();
    Object[] getArguments();
}

public class ReflectiveMethodInvocation implements MethodInvocation {

    private final Object proxy;
    private final Object target;
    private final Method method;
    private final Object[] arguments;
    private final List<?> interceptorsAndDynamicMethodMatchers;
    private int currentInterceptorIndex = -1;

    @Override
    public Object proceed() throws Throwable {
        if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
            return this.method.invoke(this.target, this.arguments);
        }

        Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
        if (interceptorOrInterceptionAdvice instanceof MethodInterceptor) {
            MethodInterceptor interceptor = (MethodInterceptor) interceptorOrInterceptionAdvice;
            return interceptor.invoke(this);
        } else {
            return proceed();
        }
    }
}
  • proceed():遞歸調(diào)用通知鏈中的下一個攔截器,最終執(zhí)行目標(biāo)方法。

通過對 Spring AOP源碼的詳細(xì)分析,我們可以看到Spring AOP是如何通過代理模式實(shí)現(xiàn)面向切面編程的。

四、Spring AOP應(yīng)用示例

下面我們通過一個簡單的 Spring AOP示例,展示如何通過AOP實(shí)現(xiàn)日志記錄。

1.定義業(yè)務(wù)類

public class UserService {
    public void createUser(String username) {
        System.out.println("Creating user: " + username);
    }
}

2.定義切面

@Aspect
public class LoggingAspect {

    @Before("execution(* UserService.createUser(..))")
    public void logBefore(JoinPoint joinPoint) {
        System.out.println("Before method: " + joinPoint.getSignature().getName());
    }
}

3.Spring配置

使用Java配置:

@Configuration
@EnableAspectJAutoProxy
public class AppConfig {

    @Bean
    public UserService userService() {
        return new UserService();
    }

    @Bean
    public LoggingAspect loggingAspect() {
        return new LoggingAspect();
    }
}

4.測試AOP功能

public class AopTest {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        UserService userService = context.getBean(UserService.class);
        userService.createUser("Alice");
    }
}

輸出結(jié)果:

Before method: createUser
Creating user: Alice

五、總結(jié)

Spring AOP通過代理模式實(shí)現(xiàn)了面向切面編程,能夠在不改變業(yè)務(wù)邏輯的情況下增強(qiáng)代碼功能。通過本文的分析,我們了解了 Spring AOP的基本概念、實(shí)現(xiàn)機(jī)制、核心組件以及如何在實(shí)際項(xiàng)目中應(yīng)用 AOP。Spring AOP的強(qiáng)大之處在于其靈活性和可擴(kuò)展性,使得開發(fā)者可以輕松地實(shí)現(xiàn)橫切關(guān)注點(diǎn)的分離和復(fù)用。

責(zé)任編輯:趙寧寧 來源: 猿java
相關(guān)推薦

2011-09-15 10:15:30

Spring

2012-09-28 10:20:14

IBMdw

2021-05-06 18:17:52

SpringAOP理解

2012-09-27 09:47:43

SpringJava面向?qū)ο?/a>

2018-10-25 16:20:23

JavaSpring AOPSpringMVC

2025-01-07 09:16:16

2022-05-26 09:03:39

AOP編程

2009-06-19 13:28:30

Spring AOPSpring 2.0

2022-06-07 07:58:45

SpringSpring AOP

2009-06-22 10:41:34

Spring.AOP

2022-02-17 13:39:09

AOP接口方式

2023-03-31 08:22:48

javassitcglibAOP

2022-06-08 08:04:28

Springservicerepository

2009-06-18 14:54:52

Spring AOP

2019-11-29 16:21:22

Spring框架集成

2009-06-19 11:09:27

Spring AOP

2009-09-29 10:00:40

Spring AOP框

2022-07-01 09:39:58

SpringAOPIOC

2011-04-26 09:33:04

SpringAOP

2012-07-11 14:31:16

SpringAop
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號