Spring AOP 源码探究

1. JDK动态代理

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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
public interface IUserService {
	void hello();
}


public class UserService implements IUserService {
	@Override
	public void hello() {
		System.out.println("hello");
	}
}

JDK代理的方法

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

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



2. CGLIB动态代理

CGLIB代理的方法

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
public void cglibProxy(){
    UserService userService = new UserService();
    Enhancer enhancer = new Enhancer();
    enhancer.setSuperclass(UserService.class);
    enhancer.setCallback(new MethodInterceptor() {
        @Override
        public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {

            if(method.getName().equals("hello")){
                System.out.println("before hello");
            }

            userService.hello();

            return null;
        }
    });
    IUserService proxy = (IUserService) enhancer.create();
    proxy.hello();
}



3. 通过ProxyFactory设置动态代理

ProxyFactory代理的方法

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

    // ☆ ->
    IUserService proxy = (IUserService) proxyFactory.getProxy();
    proxy.hello();
}

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

  • MethodBeforeAdvice

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

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

    1
    2
    
    public interface ThrowsAdvice extends AfterAdvice {
    }

    虽然这个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
    2
    3
    4
    5
    
    @FunctionalInterface
    public interface MethodInterceptor extends Interceptor {
    	@Nullable
    	Object invoke(@Nonnull MethodInvocation invocation) throws Throwable;
    }

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

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

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

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

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

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


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

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

        @Override
        public Advice getAdvice() {
            return new MethodBeforeAdvice() {
                @Override
                public void before(Method method, Object[] args, Object target) throws Throwable {
                    System.out.println("before hello");
                }
            };
        }

        @Override
        public boolean isPerInstance() {
            return false;
        }
    });

    // ☆ ->
    IUserService proxy = (IUserService) proxyFactory.getProxy();
    proxy.nihao();
    System.out.println("======================================");
    proxy.hello();
}

// 输出
// nihao
// ======================================
// before hello
// hello


4. 为Spring中的Bean动态代理

4.1. ProxyFactoryBean

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

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


4.2. BeanNameAutoProxyCreator

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

image-20240524183133005

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

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


4.3. DefaultAdvisorAutoProxyCreator

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

    DefaultPointcutAdvisor defaultPointcutAdvisor = new DefaultPointcutAdvisor();
    defaultPointcutAdvisor.setPointcut(pointcut);
    defaultPointcutAdvisor.setAdvice(new TestBeforeAdvice());
    return defaultPointcutAdvisor;
}

@Bean
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
    DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
    return defaultAdvisorAutoProxyCreator;
}

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

image-20240524183550600

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

4.4. Target和TargetSource

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

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

4.4.1. @Lazy

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

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

ContextAnnotationAutowireCandidateResolver#buildLazyResolutionProxy()

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

    ProxyFactory pf = new ProxyFactory();
    
    // 设置一个targetSource
    pf.setTargetSource(ts);
    Class<?> dependencyType = descriptor.getDependencyType();
    if (dependencyType.isInterface()) {
        pf.addInterface(dependencyType);
    }
    return pf.getProxy(dlbf.getBeanClassLoader());
}

4.5. Introduction

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

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

public interface IIntroUserService {
	public void intro();
}

public class IntroUserService implements IIntroUserService{
	public void intro() {
		System.out.println("intro");
	}
}

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

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

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

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

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

5. 代理对象创建

从ProxyFactory方法进入

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

    // ☆ ->
    IUserService proxy = (IUserService) proxyFactory.getProxy();
    proxy.hello();
}

getProxy()方法中

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

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

    可以看出:

    • 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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
public class TestPointcutAdvisor implements PointcutAdvisor {
	@Override
	public Advice getAdvice() {
		return new TestBeforeAdvice();
	}

	@Override
	public boolean isPerInstance() {
		return false;
	}

	@Override
	public Pointcut getPointcut() {
		return new Pointcut() {
			@Override
			public ClassFilter getClassFilter() {
				return new ClassFilter() {
					@Override
					public boolean matches(Class<?> clazz) {
						return false;
					}
				};
			}

			@Override
			public MethodMatcher getMethodMatcher() {
				return new MethodMatcher() {
					@Override
					public boolean matches(Method method, Class<?> targetClass) {
						return false;
					}

					@Override
					public boolean isRuntime() {
						return false;
					}

					@Override
					public boolean matches(Method method, Class<?> targetClass, Object... args) {
						return false;
					}
				};
			}
		};
	}
}

Advice转换成对应的MethodInterceptor

DefaultAdvisorAdapterRegistry#getInterceptors

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
	@Override
	public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
		List<MethodInterceptor> interceptors = new ArrayList<>(3);
		Advice advice = advisor.getAdvice();
		// 如果advice已经是MethodInterceptor对象了则直接加到Interceptors中
		if (advice instanceof MethodInterceptor) {
			interceptors.add((MethodInterceptor) advice);
		}

		// 如果不是
		// 则将Advice转换成MethodInterceptor,并添加到Interceptors中
		// adapters 有三种:
		// 1. AfterReturningAdviceAdapter --转换--> AfterReturningAdviceInterceptor  (MethodInterceptor)
		// 2. MethodBeforeAdviceAdapter   ...
		// 3. ThrowsAdviceAdapter         ...
		for (AdvisorAdapter adapter : this.adapters) {
			if (adapter.supportsAdvice(advice)) {
				interceptors.add(adapter.getInterceptor(advisor));
			}
		}
		if (interceptors.isEmpty()) {
			throw new UnknownAdviceTypeException(advisor.getAdvice());
		}
		return interceptors.toArray(new MethodInterceptor[0]);
	}

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

  • AfterReturningAdviceAdapter

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

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

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

5.2. CGLIB代理对象创建

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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {

    // ...

    // 拿到被代理的类
    Class<?> rootClass = this.advised.getTargetClass();
    Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");

    Class<?> proxySuperClass = rootClass;
    // 如果被代理的类的本身就已经是在Cglib所生成的代理类了
    if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
        // 获取真正的被代理类
        proxySuperClass = rootClass.getSuperclass();
        // 获取被代理类所实现的接口
        Class<?>[] additionalInterfaces = rootClass.getInterfaces();
        for (Class<?> additionalInterface : additionalInterfaces) {
            this.advised.addInterface(additionalInterface);
        }
    }

    // Validate the class, writing log messages as necessary.
    validateClassIfNecessary(proxySuperClass, classLoader);

    // Configure CGLIB Enhancer...
    Enhancer enhancer = createEnhancer();
    if (classLoader != null) {
        enhancer.setClassLoader(classLoader);
        if (classLoader instanceof SmartClassLoader &&
            ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
            enhancer.setUseCache(false);
        }
    }

    // 被代理类, 代理类的父亲
    enhancer.setSuperclass(proxySuperClass);
    // 代理类额外要实现的接口
    enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
    enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
    enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));

    // ☆ ->
    // 获取和被代理类所匹配的Advisor
    Callback[] callbacks = getCallbacks(rootClass);
    Class<?>[] types = new Class<?>[callbacks.length];
    for (int x = 0; x < types.length; x++) {
        types[x] = callbacks[x].getClass();
    }
    // fixedInterceptorMap only populated at this point, after getCallbacks call above
    enhancer.setCallbackFilter(new ProxyCallbackFilter(this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
    enhancer.setCallbackTypes(types);

    // Generate the proxy class and create a proxy instance.
    return createProxyClassAndInstance(enhancer, callbacks);
    
    // ...
  
}

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

1
2
3
4
5
6
7
8
private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
    // ...

    // 会进入到下面的方法:org.springframework.aop.framework.CglibAopProxy.DynamicAdvisedInterceptor.intercept
    Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);

    // ...
}

在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
2
3
4
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
    ...
}

引入了 AspectJAutoProxyRegistrar.class


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

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

Untitled

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

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


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

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

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

			// ☆ ->
			return wrapIfNecessary(bean, beanName, cacheKey);
		}
	}
	return bean;
}

继续进入方法中wrapIfNecessary()

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
		// 判断当前bean是否存在匹配的advice, 如果存在则要生成一个代理对象
		// 此处根据类以及类中的方法去匹配到Interceptor(也就是advice). 然后生成代理对象,
		// 代理对象在执行的时候, 还会根据当前执行的方法去匹配
		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
		if (specificInterceptors != DO_NOT_PROXY) {

			// advisedBeans记录了某个Bean已经进行过AOP了
			this.advisedBeans.put(cacheKey, Boolean.TRUE);

			// ☆ ->
			Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
			this.proxyTypes.put(cacheKey, proxy.getClass());
			return proxy;
		}

		this.advisedBeans.put(cacheKey, Boolean.FALSE);
		return bean;
	}

继续进入createProxy()方法

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
		if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
			return bean;
		}

		// advisedBeans表示已经判断过来的的bean, false表示此bean不需要进行Aop
		if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
			return bean;
		}

		// 当前正在创建Bean不用进行AOP, 比如切面Bean
		// shouldSkip() 是模板方法, 子类可以去扩展的
		// org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.isInfrastructureClass
		if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
			this.advisedBeans.put(cacheKey, Boolean.FALSE);

			// 直接返回
			return bean;
		}

		// ☆ ->
		// 判断当前bean是否存在匹配的advice, 如果存在则要生成一个代理对象
		// 此处根据类以及类中的方法去匹配到Interceptor(也就是advice). 然后生成代理对象,
		// 代理对象在执行的时候, 还会根据当前执行的方法去匹配
		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
		if (specificInterceptors != DO_NOT_PROXY) {

			// advisedBeans记录了某个Bean已经进行过AOP了
			this.advisedBeans.put(cacheKey, Boolean.TRUE);

			// ☆ ->
			Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
			this.proxyTypes.put(cacheKey, proxy.getClass());
			return proxy;
		}

		this.advisedBeans.put(cacheKey, Boolean.FALSE);
		return bean;
	}

该方法做了如下事情:

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

	// Build Advisors for all AspectJ aspects in the bean factory.
	// 再从所有的切面中解析得到Advisor对象
	if (this.aspectJAdvisorsBuilder != null) {

		// 解析AspectJ中定义的切面方法, 并加到advisors中
		advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
	}
	return advisors;
}

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


buildAspectJAdvisors()代码如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
public List<Advisor> buildAspectJAdvisors() {
	List<String> aspectNames = this.aspectBeanNames;

	if (aspectNames == null) {
		synchronized (this) {
			aspectNames = this.aspectBeanNames;
			if (aspectNames == null) {
				List<Advisor> advisors = new ArrayList<>();
				aspectNames = new ArrayList<>();
				String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
						this.beanFactory, Object.class, true, false);
				for (String beanName : beanNames) {
					if (!isEligibleBean(beanName)) {
						continue;
					}

					Class<?> beanType = this.beanFactory.getType(beanName, false);
					if (beanType == null) {
						continue;
					}

					// 判断类上是否有AspectJ注解
					if (this.advisorFactory.isAspect(beanType)) {
						aspectNames.add(beanName);

						// 切面的注解信息
						AspectMetadata amd = new AspectMetadata(beanType, beanName);

						// 如果@Aspect不是perthis、pertarget, 那么一个切面只会生成一个对象(单例),
						// 并且会将该切面中的所对应的Advisor对象进行缓存
						if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
							MetadataAwareAspectInstanceFactory factory = new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
              
              				// ☆ ->
							// 利用BeanFactoryAspectInstanceFactory来解析Aspect类
							List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
							if (this.beanFactory.isSingleton(beanName)) {

								// 缓存切面所对应的所有Advisor对象
								this.advisorsCache.put(beanName, classAdvisors);
							} else {
								this.aspectFactoryCache.put(beanName, factory);
							}
							advisors.addAll(classAdvisors);
						} else {
							// Per target or per this.
							if (this.beanFactory.isSingleton(beanName)) {
								throw new IllegalArgumentException("Bean with name '" + beanName + "' is a singleton, but aspect instantiation model is not singleton");
							}
							MetadataAwareAspectInstanceFactory factory = new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
							this.aspectFactoryCache.put(beanName, factory);

							// 利用PrototypeAspectInstanceFactory来解析Aspect类
							// PrototypeAspectInstanceFactory的父类为BeanFactoryAspectInstanceFactory
							// 这两个Factory的区别在于PrototypeAspectInstanceFactory的构造方法中会判断切面Bean是不是原型,
							// 除此之外没有其他区别
							//
							// 所以主要就是BeanFactoryAspectInstanceFactory来负责生成切面实例对象
							advisors.addAll(this.advisorFactory.getAdvisors(factory));
						}
					}
				}
				this.aspectBeanNames = aspectNames;
				return advisors;
			}
		}
	}

	if (aspectNames.isEmpty()) {
		return Collections.emptyList();
	}

	// 如果切面已经找到过了,那么则遍历每个切面是否缓存了对应的Advisor,如果没有缓存则进行解析得到Advisor
	List<Advisor> advisors = new ArrayList<>();
	for (String aspectName : aspectNames) {
		List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
		if (cachedAdvisors != null) {
			advisors.addAll(cachedAdvisors);
		} else {
			MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
			advisors.addAll(this.advisorFactory.getAdvisors(factory));
		}
	}
	return advisors;
}

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


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
	@Override
	public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {

    ......

		// 获取切面类中[没有]加@Pointcut的方法,进行遍历生成Advisor, 并排序
		for (Method method : getAdvisorMethods(aspectClass)) {
			Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, 0, aspectName);
			if (advisor != null) {
				advisors.add(advisor);
			}
		}

		// 如果是pertarget或perthis,则会多生成一个Advisor并放在最前面
		// 在一个代理对象调用方法的时候,就会执行该Advisor,并且会利用lazySingletonAspectInstanceFactory来生成一个切面Bean
		if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
			Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
			advisors.add(0, instantiationAdvisor);
		}

		// 找到哪些字段上加了@DeclareParents注解,把这些字段以及对于的注解解析封装为Advisor,生成代理对象时会把对于的接口添加到ProxyFactory中
		for (Field field : aspectClass.getDeclaredFields()) {
			Advisor advisor = getDeclareParentsAdvisor(field);
			if (advisor != null) {
				advisors.add(advisor);
			}
		}

		return advisors;
	}

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


排序规则:

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

	// 再根据方法名排序
	Comparator<Method> methodNameComparator = new ConvertingComparator<>(Method::getName);
	adviceMethodComparator = adviceKindComparator.thenComparing(methodNameComparator);
}

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


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

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

各注解对应的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


相关内容

0%