1. JDK动态代理

下面测试需要用到的一些基础类

 1public interface IUserService {
 2	void hello();
 3}
 4
 5
 6public class UserService implements IUserService {
 7	@Override
 8	public void hello() {
 9		System.out.println("hello");
10	}
11}

JDK代理的方法

JDK代理对象需要有一个接口,在newProxyInstance中的new Class[]{},需要加上执行代理类的接口

1public void jdkProxy(){
2    IUserService proxy = (IUserService) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{IUserService.class}, new InvocationHandler() {
3        @Override
4        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
5            return null;
6        }
7    });
8    proxy.hello();
9}



2. CGLIB动态代理

CGLIB代理的方法

 1public void cglibProxy(){
 2    UserService userService = new UserService();
 3    Enhancer enhancer = new Enhancer();
 4    enhancer.setSuperclass(UserService.class);
 5    enhancer.setCallback(new MethodInterceptor() {
 6        @Override
 7        public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
 8
 9            if(method.getName().equals("hello")){
10                System.out.println("before hello");
11            }
12
13            userService.hello();
14
15            return null;
16        }
17    });
18    IUserService proxy = (IUserService) enhancer.create();
19    proxy.hello();
20}



3. 通过ProxyFactory设置动态代理

ProxyFactory代理的方法

 1public void springAop(){
 2    UserService userService = new UserService();
 3    ProxyFactory proxyFactory = new ProxyFactory(userService);
 4    proxyFactory.setTarget(userService);
 5    proxyFactory.addAdvice(new MethodBeforeAdvice() {
 6        @Override
 7        public void before(Method method, Object[] args, Object target) throws Throwable {
 8            System.out.println("before hello");
 9        }
10    });
11
12    // ☆ ->
13    IUserService proxy = (IUserService) proxyFactory.getProxy();
14    proxy.hello();
15}

在addAdvice方法中可以是一下几种类型,当然我们也可以实现这些接口根据自己的需求自定义 对应的方法

  • MethodBeforeAdvice

    1public interface MethodBeforeAdvice extends BeforeAdvice {
    2	void before(Method method, Object[] args, @Nullable Object target) throws Throwable;
    3}
    
  • AfterReturningAdvice

    1public interface AfterReturningAdvice extends AfterAdvice {
    2	void afterReturning(@Nullable Object returnValue, Method method, Object[] args, @Nullable Object target) throws Throwable;
    3}
    
  • ThrowsAdvice: 注意这个接口中没有可以实现的方法,而且这个接口还是继承了AfterAdvice

    1public interface ThrowsAdvice extends AfterAdvice {
    2}
    

    虽然这个Advice的接口中没有可以实现的方法,但是从这个接口的注释中我们可以知道,实现了这个接口之后,会通过反射的方式调用一下方法:

    1. public void afterThrowing(Exception ex)
    2. public void afterThrowing(RemoteException)
    3. public void afterThrowing(Method method, Object[] args, Object target, Exception ex)
    4. public void afterThrowing(Method method, Object[] args, Object target, ServletException ex)

    从上面的方法可以看出,当我们在写afterThrowing方法的时候,要么之后一个参数,要么是4个,其中的Exception表示,只有是这个Exception才会来调用这个方法。相当于是一个过滤的作用。

  • MethodInterceptor: 这个是org.aopalliance.intercept;这个包下面的,不是cglib下面的。

    1@FunctionalInterface
    2public interface MethodInterceptor extends Interceptor {
    3	@Nullable
    4	Object invoke(@Nonnull MethodInvocation invocation) throws Throwable;
    5}
    

    这个接口实现了之后就更加的自由了,我们可以自己通过使用invocation.proceed()的调用来完成各种顺序的操作。比如实现Around。

    这里有一点需要注意,如果我们addAdvice()了多个Advice,那么当我们在调用invocation.proceed()的时候,会优先调用后续的Advice的内容,然后执行被代理的方法,最后执行invocation.proceed()这个方法之后的代码。我们添加进入的Advice,最终都会被封装成一个MethodInterceptor,每次在低调用invocation.proceed()的时候都会去判断当前是不是最后一个,如果是最后一个,就直接调用被代理的方法,如果不是则继续获取下一个MethodInterceptor去执行。部分源码如下:

     1// org.springframework.aop.framework.ReflectiveMethodInvocation#proceed
     2
     3// 当调用我拿了最后一个interceptor就会执行被代理的方法
     4if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
     5    return invokeJoinpoint();
     6}
     7
     8// currentInterceptorIndex初始值为-1
     9// 取出第一个MethodInterceptor
    10Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
    

    MethodInterceptor非常重要,在后面我们可以知道,所有的我们添加的Advisor到最后都会被封装成MethodInterceptor,即使你使用的事addAdvice的方法,添加了Advice,也会在被封装为Advisor,最后成为MethodInterceptor。

     1@Override
     2public void addAdvice(int pos, Advice advice) throws AopConfigException {
     3    Assert.notNull(advice, "Advice must not be null");
     4    if (advice instanceof IntroductionInfo) {
     5        // We don't need an IntroductionAdvisor for this kind of introduction:
     6        // It's fully self-describing.
     7        addAdvisor(pos, new DefaultIntroductionAdvisor(advice, (IntroductionInfo) advice));
     8    }
     9    else if (advice instanceof DynamicIntroductionAdvice) {
    10        // We need an IntroductionAdvisor for this kind of introduction.
    11        throw new AopConfigException("DynamicIntroductionAdvice may only be added as part of IntroductionAdvisor");
    12    }
    13    else {
    14        addAdvisor(pos, new DefaultPointcutAdvisor(advice));
    15    }
    16}
    

    上面第14行的DefaultPointcutAdvisor,是一个匹配所有方法的Advisor,所以通过addAdvice()这个方法添加的advice,也会被封装成为一个default的advisor


3.1. 指定方法执行指定代理

  • Advice只是一段代理逻辑
  • Advicer则可以通过Pointcut来决定这段代理逻辑在什么时候会触发,比如说在什么方法调用的时候会触发。所以Advisor可以看成Advice+Pointcut
    • 可以通过methodName来控制
    • 也可以通过被代理的类的类型targetClass来控制
 1public void springAopSpecific(){
 2    UserService userService = new UserService();
 3    ProxyFactory proxyFactory = new ProxyFactory(userService);
 4    proxyFactory.setTarget(userService);
 5    proxyFactory.addAdvisor(new PointcutAdvisor() {
 6        @Override
 7        public Pointcut getPointcut() {
 8            return new StaticMethodMatcherPointcut() {
 9                @Override
10                public boolean matches(Method method, Class<?> targetClass) {
11                    // 只有方法名为hello的才会被代理
12                    return method.getName().equals("hello");
13                }
14            };
15        }
16
17        @Override
18        public Advice getAdvice() {
19            return new MethodBeforeAdvice() {
20                @Override
21                public void before(Method method, Object[] args, Object target) throws Throwable {
22                    System.out.println("before hello");
23                }
24            };
25        }
26
27        @Override
28        public boolean isPerInstance() {
29            return false;
30        }
31    });
32
33    // ☆ ->
34    IUserService proxy = (IUserService) proxyFactory.getProxy();
35    proxy.nihao();
36    System.out.println("======================================");
37    proxy.hello();
38}
39
40// 输出
41// nihao
42// ======================================
43// before hello
44// hello


4. 为Spring中的Bean动态代理

4.1. ProxyFactoryBean

1@Bean
2public ProxyFactoryBean userService() {
3    ProxyFactoryBean proxyFactoryBean = new ProxyFactoryBean();
4    proxyFactoryBean.setTarget(new UserService());
5    proxyFactoryBean.setProxyTargetClass(true);
6    return proxyFactoryBean;
7}
image-20240524182114974

可以看到已经为UserService生成了CGLIB的代理对象。


4.2. BeanNameAutoProxyCreator

1@Bean
2public BeanNameAutoProxyCreator beanNameAutoProxyCreator() {
3    BeanNameAutoProxyCreator beanNameAutoProxyCreator = new BeanNameAutoProxyCreator();
4    beanNameAutoProxyCreator.setBeanNames("userSer*");
5    beanNameAutoProxyCreator.setInterceptorNames("testBeforeAdvice");
6    return beanNameAutoProxyCreator;
7}

image-20240524183133005

在上面的截图中我们可以看到UserService也产生了代理对象,但是使用的是JDK的动态代理。

当我们把UserService上的IUserSerivce接口去掉之后就会使用CGLIB的动态代理,如下图所示: image-20240524183403258


4.3. DefaultAdvisorAutoProxyCreator

 1@Bean
 2public DefaultPointcutAdvisor defaultPointcutAdvisor() {
 3    NameMatchMethodPointcut pointcut = new NameMatchMethodPointcut();
 4    pointcut.addMethodName("hello");
 5
 6    DefaultPointcutAdvisor defaultPointcutAdvisor = new DefaultPointcutAdvisor();
 7    defaultPointcutAdvisor.setPointcut(pointcut);
 8    defaultPointcutAdvisor.setAdvice(new TestBeforeAdvice());
 9    return defaultPointcutAdvisor;
10}
11
12@Bean
13public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
14    DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
15    return defaultAdvisorAutoProxyCreator;
16}

这里可以只为有指定方法的对象生成代理,只有有这个方法的bean才会生成对应的代理对象。

image-20240524183550600

上面的代码中DefaultAdvisorAutoProxyCreator这个类可以直接使用@Import(DefaultAdvisorAutoProxyCreator.class)注解导入,可以实现同样的效果

4.4. Target和TargetSource

正常我们在使用ProxyFactory的时候,调用setTarget(target),底层还是会将target封装成targetSource

1public void setTarget(Object target) {
2    setTargetSource(new SingletonTargetSource(target));
3}

4.4.1. @Lazy

lazy注解的底层实际上正是使用了new了一个targetSource,实现懒加载,此时的代理对象的target并不是真正的target,而是为了被代理对象不为空而由spring生成的一个targetSource对象。

当在调用targetSource的getTarget()方法的时候,才会从BeanFacotry中找到真正的bean对象。

ContextAnnotationAutowireCandidateResolver#buildLazyResolutionProxy()

 1protected Object buildLazyResolutionProxy(final DependencyDescriptor descriptor, final @Nullable String beanName) {
 2	
 3    // ...
 4    TargetSource ts = new TargetSource() {
 5        @Override
 6        public Class<?> getTargetClass() {
 7            return descriptor.getDependencyType();
 8        }
 9        @Override
10        public boolean isStatic() {
11            return false;
12        }
13        @Override
14        public Object getTarget() {
15            Set<String> autowiredBeanNames = (beanName != null ? new LinkedHashSet<>(1) : null);
16            Object target = dlbf.doResolveDependency(descriptor, beanName, autowiredBeanNames, null);
17            // ...
18            return target;
19        }
20        @Override
21        public void releaseTarget(Object target) {
22        }
23    };
24
25    ProxyFactory pf = new ProxyFactory();
26    
27    // 设置一个targetSource
28    pf.setTargetSource(ts);
29    Class<?> dependencyType = descriptor.getDependencyType();
30    if (dependencyType.isInterface()) {
31        pf.addInterface(dependencyType);
32    }
33    return pf.getProxy(dlbf.getBeanClassLoader());
34}

4.5. Introduction

比如说我现在有一个UserService的类,我需要动态的为他新增一个接口,这个时候我们就可以用到introduction。

 1@Aspect
 2@Component
 3public class TestAspect {
 4	@DeclareParents(value = "org.springframework.gang.service.UserService", defaultImpl = IntroUserService.class)
 5	public IIntroUserService introUserService;
 6}
 7
 8public interface IIntroUserService {
 9	public void intro();
10}
11
12public class IntroUserService implements IIntroUserService{
13	public void intro() {
14		System.out.println("intro");
15	}
16}

在上面的代码中,我们为UserService这个类动态的新增了一个IIntroUserService这个接口,那么接口有了,这个接口里面的方法的实现内容怎么确定呢,这个接口的实现内容需要放在另外一个实现类中,即@DeclareParents的参数中有一个defaultImpl参数。

完成了上面的代码后,我们就可以测试一下:

1public class Main {
2	public static void main(String[] args) {
3		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
4		IIntroUserService userService = (IIntroUserService) context.getBean("userService");
5		userService.intro();
6	}
7}

这时候,从context中拿到的就IIntroUserService这种类型的userService的代理对象了,此时就可以调用新增接口中的intro()方法了。

上面就是AOP中introduction的大概内容

5. 代理对象创建

从ProxyFactory方法进入

 1public void springAop(){
 2    UserService userService = new UserService();
 3    ProxyFactory proxyFactory = new ProxyFactory(userService);
 4    proxyFactory.setTarget(userService);
 5    proxyFactory.addAdvice(new MethodBeforeAdvice() {
 6        @Override
 7        public void before(Method method, Object[] args, Object target) throws Throwable {
 8            System.out.println("before hello");
 9        }
10    });
11
12    // ☆ ->
13    IUserService proxy = (IUserService) proxyFactory.getProxy();
14    proxy.hello();
15}

getProxy()方法中

1public Object getProxy() {
2    // ☆ ->
3    return createAopProxy().getProxy();
4}
  • createAopProxy():决定是使用JDK动态代理还是CGLIB动态代理

     1@Override
     2public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
     3    if (
     4        !NativeDetector.inNativeImage() &&      
     5        (
     6            config.isOptimize() ||
     7            config.isProxyTargetClass() ||
     8            hasNoUserSuppliedProxyInterfaces(config)
     9        )
    10    ) {
    11        Class<?> targetClass = config.getTargetClass();
    12        if (targetClass == null) {
    13            throw new AopConfigException("TargetSource cannot determine target class: Either an interface or a target is required for proxy creation.");
    14        }
    15        if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
    16            return new JdkDynamicAopProxy(config);
    17        }
    18        return new ObjenesisCglibAopProxy(config);
    19    } else {
    20        return new JdkDynamicAopProxy(config);
    21    }
    22}
    

    可以看出:

    • CGLIB动态代理条件:
      • 如果ProxyFactory的isOptimize设置为了true(setOptimize()方法设置) ,spring会认为cglib比jdk动态代理要快
      • isProxyTargetClass设置为true
      • 或者被代理的对象没有实现接口(需要通过addInterface()方法设置的)
      • 不是在GraalVM上虚拟机上运行的
    • JDK动态代理条件:
      • 被代理的类是接口, 或者被代理的类是进行过JDK动态代理的类, 则只能进行JDK动态代理
      • 其他情况都会进行JDK动态代理
  • getProxy():获取代理对象

    • JdkDynamicAopProxy
    • ObjenesisCglibAopProxy

    两种代理方式的代理方法执行都是在invoke()这个方法中:

    • org.springframework.aop.framework.JdkDynamicAopProxy#invoke


5.1. JDK代理对象创建

在下面的方法中会更具ClassFilter和MethodMatcher来过滤Advice

DefaultAdvisorChainFactory#getInterceptorsAndDynamicInterceptionAdvice

 1public class TestPointcutAdvisor implements PointcutAdvisor {
 2	@Override
 3	public Advice getAdvice() {
 4		return new TestBeforeAdvice();
 5	}
 6
 7	@Override
 8	public boolean isPerInstance() {
 9		return false;
10	}
11
12	@Override
13	public Pointcut getPointcut() {
14		return new Pointcut() {
15			@Override
16			public ClassFilter getClassFilter() {
17				return new ClassFilter() {
18					@Override
19					public boolean matches(Class<?> clazz) {
20						return false;
21					}
22				};
23			}
24
25			@Override
26			public MethodMatcher getMethodMatcher() {
27				return new MethodMatcher() {
28					@Override
29					public boolean matches(Method method, Class<?> targetClass) {
30						return false;
31					}
32
33					@Override
34					public boolean isRuntime() {
35						return false;
36					}
37
38					@Override
39					public boolean matches(Method method, Class<?> targetClass, Object... args) {
40						return false;
41					}
42				};
43			}
44		};
45	}
46}

Advice转换成对应的MethodInterceptor

DefaultAdvisorAdapterRegistry#getInterceptors

 1	@Override
 2	public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
 3		List<MethodInterceptor> interceptors = new ArrayList<>(3);
 4		Advice advice = advisor.getAdvice();
 5		// 如果advice已经是MethodInterceptor对象了则直接加到Interceptors中
 6		if (advice instanceof MethodInterceptor) {
 7			interceptors.add((MethodInterceptor) advice);
 8		}
 9
10		// 如果不是
11		// 则将Advice转换成MethodInterceptor,并添加到Interceptors中
12		// adapters 有三种:
13		// 1. AfterReturningAdviceAdapter --转换--> AfterReturningAdviceInterceptor  (MethodInterceptor)
14		// 2. MethodBeforeAdviceAdapter   ...
15		// 3. ThrowsAdviceAdapter         ...
16		for (AdvisorAdapter adapter : this.adapters) {
17			if (adapter.supportsAdvice(advice)) {
18				interceptors.add(adapter.getInterceptor(advisor));
19			}
20		}
21		if (interceptors.isEmpty()) {
22			throw new UnknownAdviceTypeException(advisor.getAdvice());
23		}
24		return interceptors.toArray(new MethodInterceptor[0]);
25	}

AfterReturningAdviceAdapterMethodBeforeAdviceAdapterThrowsAdviceAdapter三个类中的都会有一个getInterceptor(),这是在这个方法中将Advice转成了对应的MethodInterceptor的,最后实际上执行的代理方法正式对应MethodInterceptorinvoke()方法,详细如下:

  • AfterReturningAdviceAdapter

     1// AfterReturningAdviceAdapter.java
     2public MethodInterceptor getInterceptor(Advisor advisor) {
     3    AfterReturningAdvice advice = (AfterReturningAdvice) advisor.getAdvice();
     4    return new AfterReturningAdviceInterceptor(advice);
     5}
     6
     7// AfterReturningAdviceInterceptor.java
     8public Object invoke(MethodInvocation mi) throws Throwable {
     9    Object retVal = mi.proceed();
    10    this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
    11    return retVal;
    12}
    
  • MethodBeforeAdviceAdapter

     1// MethodBeforeAdviceAdapter.java
     2public MethodInterceptor getInterceptor(Advisor advisor) {
     3    MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
     4    return new MethodBeforeAdviceInterceptor(advice);
     5}
     6
     7// MethodBeforeAdviceInterceptor.java
     8public Object invoke(MethodInvocation mi) throws Throwable {
     9    this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
    10    return mi.proceed();
    11}
    
  • ThrowsAdviceAdapter

     1// ThrowsAdviceAdapter.java
     2public MethodInterceptor getInterceptor(Advisor advisor) {
     3    return new ThrowsAdviceInterceptor(advisor.getAdvice());
     4}
     5
     6// ThrowsAdviceInterceptor.java
     7public Object invoke(MethodInvocation mi) throws Throwable {
     8    try {
     9        return mi.proceed();
    10    } catch (Throwable ex) {
    11        Method handlerMethod = getExceptionHandler(ex);
    12        if (handlerMethod != null) {
    13            invokeHandlerMethod(mi, ex, handlerMethod);
    14        }
    15        throw ex;
    16    }
    17}
    

5.2. CGLIB代理对象创建

ProxyFactory#getProxy() 方法选择CGLIB的实现后即可进入CGLIB代理相关的方法

 1@Override
 2public Object getProxy(@Nullable ClassLoader classLoader) {
 3
 4    // ...
 5
 6    // 拿到被代理的类
 7    Class<?> rootClass = this.advised.getTargetClass();
 8    Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");
 9
10    Class<?> proxySuperClass = rootClass;
11    // 如果被代理的类的本身就已经是在Cglib所生成的代理类了
12    if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
13        // 获取真正的被代理类
14        proxySuperClass = rootClass.getSuperclass();
15        // 获取被代理类所实现的接口
16        Class<?>[] additionalInterfaces = rootClass.getInterfaces();
17        for (Class<?> additionalInterface : additionalInterfaces) {
18            this.advised.addInterface(additionalInterface);
19        }
20    }
21
22    // Validate the class, writing log messages as necessary.
23    validateClassIfNecessary(proxySuperClass, classLoader);
24
25    // Configure CGLIB Enhancer...
26    Enhancer enhancer = createEnhancer();
27    if (classLoader != null) {
28        enhancer.setClassLoader(classLoader);
29        if (classLoader instanceof SmartClassLoader &&
30            ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
31            enhancer.setUseCache(false);
32        }
33    }
34
35    // 被代理类, 代理类的父亲
36    enhancer.setSuperclass(proxySuperClass);
37    // 代理类额外要实现的接口
38    enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
39    enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
40    enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));
41
42    // ☆ ->
43    // 获取和被代理类所匹配的Advisor
44    Callback[] callbacks = getCallbacks(rootClass);
45    Class<?>[] types = new Class<?>[callbacks.length];
46    for (int x = 0; x < types.length; x++) {
47        types[x] = callbacks[x].getClass();
48    }
49    // fixedInterceptorMap only populated at this point, after getCallbacks call above
50    enhancer.setCallbackFilter(new ProxyCallbackFilter(this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
51    enhancer.setCallbackTypes(types);
52
53    // Generate the proxy class and create a proxy instance.
54    return createProxyClassAndInstance(enhancer, callbacks);
55    
56    // ...
57  
58}

上面的代码中从44行的getCallbacks()方法中返回了和代理类相匹配的Advisor。

1private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
2    // ...
3
4    // 会进入到下面的方法:org.springframework.aop.framework.CglibAopProxy.DynamicAdvisedInterceptor.intercept
5    Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);
6
7    // ...
8}

在CglibAopProxy中有个内部类DynamicAdvisedInterceptor,包含了的intercept()方法将会被调用,和JdkDynamicAopProxy中的invoke()方法有着异曲同工的作用。都会调用this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);获取到所有的Advisor。



6. 一些名词汇总

  1. Aspect:表示切面,比如被@Aspect注解的类就是切面
  2. Join Point:表示连节点,表示程序在执行过程中的一个点,比如一个方法的执行,比如一个异常的处理,在SpiringAop中,一个连节点通常表示一个方法的执行
  3. Advice:表示通知,特定连节点上采取的动作,Advice分为不同的理性
  4. Pointcut:表示切点,用来匹配一个或者多个连节点,Advice与切点表达式是关联在一起的,Advice将会执行在和切点表达式锁匹配的连接点上
  5. Introduction:可以使用@DeclareParents来给所匹配的类添加一个接口
  6. Target object:目标对象被代理对象
  7. Aop Proxy:表示代理工厂,用来的创建代理对象的,在Spring Framework中,要么是JDK动态代理,要么是CGLIB代理
  8. Weaving:表示织入,表示创建代理对象的动作,这个动作可以发生在编译期时期,或者运行时,比如Spring AOP



7. Spring AOP 大致流程

Untitled



8. Spring Bean代理对象创建流程

1@Import(AspectJAutoProxyRegistrar.class)
2public @interface EnableAspectJAutoProxy {
3    ...
4}

引入了 AspectJAutoProxyRegistrar.class


AspectJAutoProxyRegistrar中, 通过在初始化容器实例化对象之前, 回调registerBeanDefinitions()的方法,向BeanDefinition中注册一个 AnnotationAwareAspectJAutoProxyCreator.class

1@Override
2public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
3	...
4	AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
5	...
6}

Untitled

在上图中我们看到AnnotationAwareAspectJAutoProxyCreator是实现了BeanPostProcessor接口的,

而实现BeanPostProcessor后,当Spring在Bean的初始化后会调用其postProcessAfterInitialization()方法,AOP逻辑由此开始。


接着进入postProcessAfterInitialization() 这个方法的逻辑

找到了AnnotationAwareAspectJAutoProxyCreator的父类AbstractAutoProxyCreator 中的这个方法 org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessAfterInitialization

 1@Override
 2public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
 3	if (bean != null) {
 4		Object cacheKey = getCacheKey(bean.getClass(), beanName);
 5		if (this.earlyProxyReferences.remove(cacheKey) != bean) {
 6
 7			// ☆ ->
 8			return wrapIfNecessary(bean, beanName, cacheKey);
 9		}
10	}
11	return bean;
12}

继续进入方法中wrapIfNecessary()

 1protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
 2		// 判断当前bean是否存在匹配的advice, 如果存在则要生成一个代理对象
 3		// 此处根据类以及类中的方法去匹配到Interceptor(也就是advice). 然后生成代理对象,
 4		// 代理对象在执行的时候, 还会根据当前执行的方法去匹配
 5		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
 6		if (specificInterceptors != DO_NOT_PROXY) {
 7
 8			// advisedBeans记录了某个Bean已经进行过AOP了
 9			this.advisedBeans.put(cacheKey, Boolean.TRUE);
10
11			// ☆ ->
12			Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
13			this.proxyTypes.put(cacheKey, proxy.getClass());
14			return proxy;
15		}
16
17		this.advisedBeans.put(cacheKey, Boolean.FALSE);
18		return bean;
19	}

继续进入createProxy()方法

 1protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
 2		if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
 3			return bean;
 4		}
 5
 6		// advisedBeans表示已经判断过来的的bean, false表示此bean不需要进行Aop
 7		if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
 8			return bean;
 9		}
10
11		// 当前正在创建Bean不用进行AOP, 比如切面Bean
12		// shouldSkip() 是模板方法, 子类可以去扩展的
13		// org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.isInfrastructureClass
14		if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
15			this.advisedBeans.put(cacheKey, Boolean.FALSE);
16
17			// 直接返回
18			return bean;
19		}
20
21		// ☆ ->
22		// 判断当前bean是否存在匹配的advice, 如果存在则要生成一个代理对象
23		// 此处根据类以及类中的方法去匹配到Interceptor(也就是advice). 然后生成代理对象,
24		// 代理对象在执行的时候, 还会根据当前执行的方法去匹配
25		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
26		if (specificInterceptors != DO_NOT_PROXY) {
27
28			// advisedBeans记录了某个Bean已经进行过AOP了
29			this.advisedBeans.put(cacheKey, Boolean.TRUE);
30
31			// ☆ ->
32			Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
33			this.proxyTypes.put(cacheKey, proxy.getClass());
34			return proxy;
35		}
36
37		this.advisedBeans.put(cacheKey, Boolean.FALSE);
38		return bean;
39	}

该方法做了如下事情:

  1. 进入方法后判断当前Bean是需要进行AOP,advisedBeans相当于是一个缓存,在下面判断过的bean会放入这个map中,避免再次到下面去判断。
  2. 判断当前bean是否存在匹配的advice, 匹配的条件是向根据类名,再根据方法名(如果有必要的话),如果存在则要生成一个代理对象,此处根据类以及类中的方法去匹配到Interceptor(也就是advice). 然后生成代理对象,
  3. 通过 AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors() 这个方法找到所有的Advisor
 1@Override
 2protected List<Advisor> findCandidateAdvisors() {
 3	// Add all the Spring advisors found according to superclass rules.
 4	// 找到所有Advisor类型的Bean对象
 5	List<Advisor> advisors = super.findCandidateAdvisors();
 6
 7	// Build Advisors for all AspectJ aspects in the bean factory.
 8	// 再从所有的切面中解析得到Advisor对象
 9	if (this.aspectJAdvisorsBuilder != null) {
10
11		// 解析AspectJ中定义的切面方法, 并加到advisors中
12		advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
13	}
14	return advisors;
15}

在该方法中会调用BeanFactoryAspectJAdvisorsBuilder#buildAspectJAdvisors() 把Bean都解析成Advisor, 并在list中返回


buildAspectJAdvisors()代码如下:

 1public List<Advisor> buildAspectJAdvisors() {
 2	List<String> aspectNames = this.aspectBeanNames;
 3
 4	if (aspectNames == null) {
 5		synchronized (this) {
 6			aspectNames = this.aspectBeanNames;
 7			if (aspectNames == null) {
 8				List<Advisor> advisors = new ArrayList<>();
 9				aspectNames = new ArrayList<>();
10				String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
11						this.beanFactory, Object.class, true, false);
12				for (String beanName : beanNames) {
13					if (!isEligibleBean(beanName)) {
14						continue;
15					}
16
17					Class<?> beanType = this.beanFactory.getType(beanName, false);
18					if (beanType == null) {
19						continue;
20					}
21
22					// 判断类上是否有AspectJ注解
23					if (this.advisorFactory.isAspect(beanType)) {
24						aspectNames.add(beanName);
25
26						// 切面的注解信息
27						AspectMetadata amd = new AspectMetadata(beanType, beanName);
28
29						// 如果@Aspect不是perthis、pertarget, 那么一个切面只会生成一个对象(单例),
30						// 并且会将该切面中的所对应的Advisor对象进行缓存
31						if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
32							MetadataAwareAspectInstanceFactory factory = new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
33              
34              				// ☆ ->
35							// 利用BeanFactoryAspectInstanceFactory来解析Aspect类
36							List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
37							if (this.beanFactory.isSingleton(beanName)) {
38
39								// 缓存切面所对应的所有Advisor对象
40								this.advisorsCache.put(beanName, classAdvisors);
41							} else {
42								this.aspectFactoryCache.put(beanName, factory);
43							}
44							advisors.addAll(classAdvisors);
45						} else {
46							// Per target or per this.
47							if (this.beanFactory.isSingleton(beanName)) {
48								throw new IllegalArgumentException("Bean with name '" + beanName + "' is a singleton, but aspect instantiation model is not singleton");
49							}
50							MetadataAwareAspectInstanceFactory factory = new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
51							this.aspectFactoryCache.put(beanName, factory);
52
53							// 利用PrototypeAspectInstanceFactory来解析Aspect类
54							// PrototypeAspectInstanceFactory的父类为BeanFactoryAspectInstanceFactory
55							// 这两个Factory的区别在于PrototypeAspectInstanceFactory的构造方法中会判断切面Bean是不是原型,
56							// 除此之外没有其他区别
57							//
58							// 所以主要就是BeanFactoryAspectInstanceFactory来负责生成切面实例对象
59							advisors.addAll(this.advisorFactory.getAdvisors(factory));
60						}
61					}
62				}
63				this.aspectBeanNames = aspectNames;
64				return advisors;
65			}
66		}
67	}
68
69	if (aspectNames.isEmpty()) {
70		return Collections.emptyList();
71	}
72
73	// 如果切面已经找到过了,那么则遍历每个切面是否缓存了对应的Advisor,如果没有缓存则进行解析得到Advisor
74	List<Advisor> advisors = new ArrayList<>();
75	for (String aspectName : aspectNames) {
76		List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
77		if (cachedAdvisors != null) {
78			advisors.addAll(cachedAdvisors);
79		} else {
80			MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
81			advisors.addAll(this.advisorFactory.getAdvisors(factory));
82		}
83	}
84	return advisors;
85}

上面方法中: List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);


 1	@Override
 2	public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
 3
 4    ......
 5
 6		// 获取切面类中[没有]加@Pointcut的方法,进行遍历生成Advisor, 并排序
 7		for (Method method : getAdvisorMethods(aspectClass)) {
 8			Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, 0, aspectName);
 9			if (advisor != null) {
10				advisors.add(advisor);
11			}
12		}
13
14		// 如果是pertarget或perthis,则会多生成一个Advisor并放在最前面
15		// 在一个代理对象调用方法的时候,就会执行该Advisor,并且会利用lazySingletonAspectInstanceFactory来生成一个切面Bean
16		if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
17			Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
18			advisors.add(0, instantiationAdvisor);
19		}
20
21		// 找到哪些字段上加了@DeclareParents注解,把这些字段以及对于的注解解析封装为Advisor,生成代理对象时会把对于的接口添加到ProxyFactory中
22		for (Field field : aspectClass.getDeclaredFields()) {
23			Advisor advisor = getDeclareParentsAdvisor(field);
24			if (advisor != null) {
25				advisors.add(advisor);
26			}
27		}
28
29		return advisors;
30	}

在上面的代码中: getAdvisorMethods(aspectClass) 会获取切面类中没有加@Pointcut的方法,进行遍历生成Advisor, 并排序。


排序规则:

 1static {
 2	// 先更具下面的注解排序
 3	Comparator<Method> adviceKindComparator = new ConvertingComparator<>(
 4			new InstanceComparator<>(
 5					Around.class,
 6					Before.class,
 7					After.class,
 8					AfterReturning.class,
 9					AfterThrowing.class
10			),
11			(Converter<Method, Annotation>) method -> {
12				AspectJAnnotation<?> ann = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(method);
13				return (ann != null ? ann.getAnnotation() : null);
14			});
15
16	// 再根据方法名排序
17	Comparator<Method> methodNameComparator = new ConvertingComparator<>(Method::getName);
18	adviceMethodComparator = adviceKindComparator.thenComparing(methodNameComparator);
19}

继续回到 Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, 0, aspectName); 该方法返回的对象是Advisor的实现类InstantiationModelAwarePointcutAdvisorImpl


InstantiationModelAwarePointcutAdvisorImpl#instantiateAdvice() 方法中会根据方法上的注解生成对应的Advice。

 1// 按不同的注解类型得到不同的Advice
 2switch (aspectJAnnotation.getAnnotationType()) {
 3	case AtPointcut:
 4		if (logger.isDebugEnabled()) {
 5			logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
 6		}
 7		return null;
 8	case AtAround:
 9		springAdvice = new AspectJAroundAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
10		break;
11	case AtBefore:
12		springAdvice = new AspectJMethodBeforeAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
13		break;
14	case AtAfter:
15		springAdvice = new AspectJAfterAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
16		break;
17	case AtAfterReturning:
18		springAdvice = new AspectJAfterReturningAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
19		AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
20		if (StringUtils.hasText(afterReturningAnnotation.returning())) {
21			springAdvice.setReturningName(afterReturningAnnotation.returning());
22		}
23		break;
24	case AtAfterThrowing:
25		springAdvice = new AspectJAfterThrowingAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
26		AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
27		if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
28			springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
29		}
30		break;
31	default:
32		throw new UnsupportedOperationException("Unsupported advice type on method: " + candidateAdviceMethod);
33}

各注解对应的MethodInterceptor

  • @Before:对应的是AspectJMethodBeforeAdvice,在进行动态代理时会把AspectJMethodBeforeAdvice转成MethodBeforeAdviceInterceptor
    • 先执行advice对应的方法
    • 再执行MethodInvocation的proceed(),会执行下一个Interceptor,如果没有下一个Interceptor了,会执行target对应的方法
  • @After:对应的是AspectJAfterAdvice,直接实现了MethodInterceptor
    • 先执行MethodInvocation的proceed(),会执行下一个Interceptor,如果没有下一个Interceptor了,会执行target对应的方法
    • 再执行advice对应的方法
  • @Around:对应的是AspectJAroundAdvice,直接实现了MethodInterceptor
    • 直接执行advice对应的方法,由@Around自己决定要不要继续往后面调用
  • @AfterThrowing:对应的是AspectJAfterThrowingAdvice,直接实现了MethodInterceptor
    • 先执行MethodInvocation的proceed(),会执行下一个Interceptor,如果没有下一个Interceptor了,会执行target对应的方法
    • 如果上面抛了Throwable,那么则会执行advice对应的方法
  • @AfterReturning:对应的是AspectJAfterReturningAdvice,在进行动态代理时会把AspectJAfterReturningAdvice转成AfterReturningAdviceInterceptor
    • 先执行MethodInvocation的proceed(),会执行下一个Interceptor,如果没有下一个Interceptor了,会执行target对应的方法
    • 执行上面的方法后得到最终的方法的返回值
    • 再执行Advice对应的方法

在AspectJ中有五种注解,而Spring中中只有四种Advice

— END —