spring5 源码深度解析----- AOP代理的生成

摘要:
=DO_NOT_PROXY){18this.advisedBeans.put;19Objectproxy=createProxy;21this.proxyTypes.put;22returnproxy;23}2425this.advisedBeans.put;26returnbean;27}我们上一篇文章分析完了第16行,获取到了所有对应bean的增强器,并获取到了此目标bean所有匹配的Advisor,接下来我们要从第17行开始分析,如果specificInterceptors不为空,则要为当前bean创建代理类,接下来我们来看创建代理类的方法createProxy:protectedObjectcreateProxy(ClassbeanClass,@NullableStringbeanName,@NullableObject[]specificInterceptors,TargetSourcetargetSource){if{AutoProxyUtils.exposeTargetClass;}ProxyFactoryproxyFactory=newProxyFactory();//获取当前类中相关属性proxyFactory.copyFrom;if(!proxyFactory.isProxyTargetClass()){//决定对于给定的bean是否应该使用targetClass而不是他的接口代理,//检査proxyTargetClass设置以及preserveTargetClass属性if{proxyFactory.setProxyTargetClass;}else{evaluateProxyInterfaces;}}Advisor[]advisors=buildAdvisors;//加入增强器proxyFactory.addAdvisors;//设置要代理的目标类proxyFactory.setTargetSource;//定制代理customizeProxyFactory;//用来控制代理工厂被配置之后,是否还允许修改通知。

在获取了所有对应bean的增强后,便可以进行代理的创建了。回到AbstractAutoProxyCreator的wrapIfNecessary方法中,如下所示:

1 protected static final Object[] DO_NOT_PROXY = null;
2 
3 protectedObject wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
4     if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
5         returnbean;
6 }
7     if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
8         returnbean;
9 }
10     if (isInfrastructureClass(bean.getClass()) ||shouldSkip(bean.getClass(), beanName)) {
11         this.advisedBeans.put(cacheKey, Boolean.FALSE);
12         returnbean;
13 }
14 
15     //Create proxy if we have advice.
16    Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
17     if (specificInterceptors !=DO_NOT_PROXY) {
18         this.advisedBeans.put(cacheKey, Boolean.TRUE);
19        Object proxy =createProxy(
20                 bean.getClass(), beanName, specificInterceptors, newSingletonTargetSource(bean));
21         this.proxyTypes.put(cacheKey, proxy.getClass());
22         returnproxy;
23 }
24 
25     this.advisedBeans.put(cacheKey, Boolean.FALSE);
26     returnbean;
27 }

我们上一篇文章分析完了第16行,获取到了所有对应bean的增强器,并获取到了此目标bean所有匹配的Advisor,接下来我们要从第17行开始分析,如果specificInterceptors 不为空,则要为当前bean创建代理类,接下来我们来看创建代理类的方法createProxy:

protected Object createProxy(Class<?>beanClass, @Nullable String beanName,
        @Nullable Object[] specificInterceptors, TargetSource targetSource) {
    if (this.beanFactory instanceofConfigurableListableBeanFactory) {
        AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
    }
    ProxyFactory proxyFactory = newProxyFactory();
    //获取当前类中相关属性
    proxyFactory.copyFrom(this);
    if (!proxyFactory.isProxyTargetClass()) {
        //决定对于给定的bean是否应该使用targetClass而不是他的接口代理,
        //检査 proxyTargetClass 设置以及 preserveTargetClass 属性
        if(shouldProxyTargetClass(beanClass, beanName)) {
            proxyFactory.setProxyTargetClass(true);
        }
        else{
            evaluateProxyInterfaces(beanClass, proxyFactory);
        }
    }
    Advisor[] advisors =buildAdvisors(beanName, specificInterceptors);
    //加入增强器
proxyFactory.addAdvisors(advisors);
    //设置要代理的目标类
proxyFactory.setTargetSource(targetSource);
    //定制代理
customizeProxyFactory(proxyFactory);
    //用来控制代理工厂被配置之后,是否还允许修改通知。
    //缺省值是false (即在代理被配置之后,不允许修改代理的配置)。
    proxyFactory.setFrozen(this.freezeProxy);
    if(advisorsPreFiltered()) {
        proxyFactory.setPreFiltered(true);
    }
    //真正创建代理的方法
    returnproxyFactory.getProxy(getProxyClassLoader());
}
@Override
public voidsetTargetSource(@Nullable TargetSource targetSource) {
    this.targetSource = (targetSource != null ?targetSource : EMPTY_TARGET_SOURCE);
}
public void addAdvisors(Collection<Advisor>advisors) {
    if(isFrozen()) {
        throw new AopConfigException("Cannot add advisor: Configuration is frozen.");
    }
    if (!CollectionUtils.isEmpty(advisors)) {
        for(Advisor advisor : advisors) {
            if (advisor instanceofIntroductionAdvisor) {
                validateIntroductionAdvisor((IntroductionAdvisor) advisor);
            }
            Assert.notNull(advisor, "Advisor must not be null");
            this.advisors.add(advisor);
        }
        updateAdvisorArray();
        adviceChanged();
    }
}

从上面代码我们看到对于代理类的创建及处理spring是委托给了ProxyFactory处理的

创建代理

publicObject getProxy(@Nullable ClassLoader classLoader) {
    returncreateAopProxy().getProxy(classLoader);
}

在上面的getProxy方法中createAopProxy方法,其实现是在DefaultAopProxyFactory中,这个方法的主要功能是,根据optimize、ProxyTargetClass等参数来决定生成Jdk动态代理,还是生成Cglib代理。我们进入到方法内:

protected final synchronizedAopProxy createAopProxy() {
    if (!this.active) {
        activate();
    }
    //创建代理
    return getAopProxyFactory().createAopProxy(this);
}
public AopProxy createAopProxy(AdvisedSupport config) throwsAopConfigException {
    if (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.");
        }
        //手动设置创建Cglib代理类后,如果目标bean是一个接口,也要创建jdk代理类
        if (targetClass.isInterface() ||Proxy.isProxyClass(targetClass)) {
            return newJdkDynamicAopProxy(config);
        }
        //创建Cglib代理
        return newObjenesisCglibAopProxy(config);
    }
    else{
        //默认创建jdk代理
        return newJdkDynamicAopProxy(config);
    }
}

我们知道对于Spring的代理是通过JDKProxy的实现和CglibProxy实现。Spring是如何选取的呢?

从if的判断条件中可以看到3个方面影响这Spring的判断。

  • optimize:用来控制通过CGLIB创建的代理是否使用激进的优化策略,除非完全了解AOP代理如何处理优化,否则不推荐用户使用这个设置。目前这个属性仅用于CGLIB 代理,对于JDK动态代理(缺省代理)无效。

  • proxyTargetClass:这个属性为true时,目标类本身被代理而不是目标类的接口。如果这个属性值被设为true,CGLIB代理将被创建,设置方式:<aop:aspectj-autoproxy proxy-target- />。

  • hasNoUserSuppliedProxylnterfaces:是否存在代理接口

下面是对JDK与Cglib方式的总结。

  • 如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP。

  • 如果目标对象实现了接口,可以强制使用CGLIB实现AOP。

  • 如果目标对象没有实现了接口,必须采用CGLIB库,Spring会自动在JDK动态代理 和CGLIB之间转换。

如何强制使用CGLIB实现AOP?

(1)添加 CGLIB 库,Spring_HOME/cglib/*.jar。

(2)在 Spring 配置文件中加人<aop:aspectj-autoproxy proxy-target- />。

JDK动态代理和CGLIB字节码生成的区别?

  • JDK动态代理只能对实现了接口的类生成代理,而不能针对类。
  • CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法,因为是继承,所以该类或方法最好不要声明成final。

获取代理

本文主要介绍JDK动态代理类的实现,在此之前,有必要熟悉一下JDK代理使用示例,请看我以前的博文,JDK动态代理源码分析文章《java基础(十八)----- java动态代理原理源码解析

Spring的AOP实现其实也是用了Proxy和InvocationHandler这两个东西的。

我们再次来回顾一下使用JDK代理的方式,在整个创建过程中,对于InvocationHandler的创建是最为核心的,在自定义的InvocationHandler中需要重写3个函数。

  • 构造函数,将代理的对象传入。
  • invoke方法,此方法中实现了 AOP增强的所有逻辑。
  • getProxy方法,此方法千篇一律,但是必不可少。

那么,我们看看Spring中的JDK代理实现是不是也是这么做的呢?我们来看看简化后的JdkDynamicAopProxy。

1 final class JdkDynamicAopProxy implementsAopProxy, InvocationHandler, Serializable {
2 
3     private finalAdvisedSupport advised;
4 
5     public JdkDynamicAopProxy(AdvisedSupport config) throwsAopConfigException {
6         Assert.notNull(config, "AdvisedSupport must not be null");
7         if (config.getAdvisors().length == 0 && config.getTargetSource() ==AdvisedSupport.EMPTY_TARGET_SOURCE) {
8             throw new AopConfigException("No advisors and no TargetSource specified");
9 }
10         this.advised =config;
11 }
12 
13 
14 @Override
15     publicObject getProxy() {
16         returngetProxy(ClassUtils.getDefaultClassLoader());
17 }
18 
19 @Override
20     publicObject getProxy(@Nullable ClassLoader classLoader) {
21         if(logger.isTraceEnabled()) {
22             logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
23 }
24         Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
25 findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
26      return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
27 }
28 
29 @Override
30 @Nullable
31     public Object invoke(Object proxy, Method method, Object[] args) throwsThrowable {
32         Object oldProxy = null;
33         boolean setProxyContext = false;
34 
35         TargetSource targetSource = this.advised.targetSource;
36         Object target = null;
37 
38         try{
39             if (!this.equalsDefined &&AopUtils.isEqualsMethod(method)) {
40                 //The target does not implement the equals(Object) method itself.
41                 return equals(args[0]);
42 }
43             else if (!this.hashCodeDefined &&AopUtils.isHashCodeMethod(method)) {
44                 //The target does not implement the hashCode() method itself.
45                 returnhashCode();
46 }
47             else if (method.getDeclaringClass() == DecoratingProxy.class) {
48                 //There is only getDecoratedClass() declared -> dispatch to proxy config.
49                 return AopProxyUtils.ultimateTargetClass(this.advised);
50 }
51             else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
52                     method.getDeclaringClass().isAssignableFrom(Advised.class)) {
53                 //Service invocations on ProxyConfig with the proxy config...
54                 return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
55 }
56 
57 Object retVal;
58 
59             if (this.advised.exposeProxy) {
60                 //Make invocation available if necessary.
61                 oldProxy =AopContext.setCurrentProxy(proxy);
62                 setProxyContext = true;
63 }
64 
65             //Get as late as possible to minimize the time we "own" the target,
66             //in case it comes from a pool.
67             target =targetSource.getTarget();
68             Class<?> targetClass = (target != null ? target.getClass() : null);
69 
70             //Get the interception chain for this method.
71             List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
72 
73             //Check whether we have any advice. If we don't, we can fallback on direct
74             //reflective invocation of the target, and avoid creating a MethodInvocation.
75             if(chain.isEmpty()) {
76                 //We can skip creating a MethodInvocation: just invoke the target directly
77                 //Note that the final invoker must be an InvokerInterceptor so we know it does
78                 //nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
79                 Object[] argsToUse =AopProxyUtils.adaptArgumentsIfNecessary(method, args);
80                 retVal =AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
81 }
82             else{
83                 //We need to create a method invocation...
84                 MethodInvocation invocation =
85                         newReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
86                 //Proceed to the joinpoint through the interceptor chain.
87                 retVal =invocation.proceed();
88 }
89 
90             //Massage return value if necessary.
91             Class<?> returnType =method.getReturnType();
92             if (retVal != null && retVal == target &&
93                     returnType != Object.class && returnType.isInstance(proxy) &&
94                     !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
95                 //Special case: it returned "this" and the return type of the method
96                 //is type-compatible. Note that we can't help if the target sets
97                 //a reference to itself in another returned object.
98                 retVal =proxy;
99 }
100             else if (retVal == null && returnType != Void.TYPE &&returnType.isPrimitive()) {
101                 throw newAopInvocationException(
102                         "Null return value from advice does not match primitive return type for: " +method);
103 }
104             returnretVal;
105 }
106         finally{
107             if (target != null && !targetSource.isStatic()) {
108                 //Must have come from TargetSource.
109 targetSource.releaseTarget(target);
110 }
111             if(setProxyContext) {
112                 //Restore old proxy.
113 AopContext.setCurrentProxy(oldProxy);
114 }
115 }
116 }
117 
118 }

我们看到JdkDynamicAopProxy 也是和我们自定义的InvocationHandler一样,实现了InvocationHandler接口,并且提供了一个getProxy方法创建代理类,重写invoke方法。

我们重点看看代理类的调用。了解Jdk动态代理的话都会知道,在实现Jdk动态代理功能,要实现InvocationHandler接口的invoke方法(这个方法是一个回调方法)。被代理类中的方法被调用时,实际上是调用的invoke方法,我们看一看这个方法的实现。

1 @Override
2 @Nullable
3 public Object invoke(Object proxy, Method method, Object[] args) throwsThrowable {
4 MethodInvocation invocation;
5     Object oldProxy = null;
6     boolean setProxyContext = false;
7 
8     TargetSource targetSource = this.advised.targetSource;
9     Object target = null;
10 
11     try{
12         if (!this.equalsDefined &&AopUtils.isEqualsMethod(method)) {
13             return equals(args[0]);
14 }
15         else if (!this.hashCodeDefined &&AopUtils.isHashCodeMethod(method)) {
16             returnhashCode();
17 }
18         else if (method.getDeclaringClass() == DecoratingProxy.class) {
19             return AopProxyUtils.ultimateTargetClass(this.advised);
20 }
21         else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
22                 method.getDeclaringClass().isAssignableFrom(Advised.class)) {
23             return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
24 }
25 
26 Object retVal;
27         if (this.advised.exposeProxy) {
28             //Make invocation available if necessary.
29             oldProxy =AopContext.setCurrentProxy(proxy);
30             setProxyContext = true;
31 }
32 
33         target =targetSource.getTarget();
34         Class<?> targetClass = (target != null ? target.getClass() : null);
35 
36         //获取当前方法的拦截器链
37        List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
38 
39         if(chain.isEmpty()) {
40             //如果没有发现任何拦截器那么直接调用切点方法
41             Object[] argsToUse =AopProxyUtils.adaptArgumentsIfNecessary(method, args);
42             retVal =AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
43 }
44         else{
45             //We need to create a method invocation...
46             //将拦截器封装在ReflectiveMethodInvocation,
47             //以便于使用其proceed进行链接表用拦截器
48          invocation = newReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
49             //Proceed to the joinpoint through the interceptor chain.
50             //执行拦截器链
51           retVal =invocation.proceed();
52 }
53 
54         Class<?> returnType =method.getReturnType();
55         //返回结果
56         if (retVal != null && retVal == target &&
57                 returnType != Object.class && returnType.isInstance(proxy) &&
58                 !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
59             retVal =proxy;
60 }
61         else if (retVal == null && returnType != Void.TYPE &&returnType.isPrimitive()) {
62             throw newAopInvocationException(
63                     "Null return value from advice does not match primitive return type for: " +method);
64 }
65         returnretVal;
66 }
67     finally{
68         if (target != null && !targetSource.isStatic()) {
69             //Must have come from TargetSource.
70 targetSource.releaseTarget(target);
71 }
72         if(setProxyContext) {
73             //Restore old proxy.
74 AopContext.setCurrentProxy(oldProxy);
75 }
76 }
77 }

我们先来看看第37行,获取目标bean中目标method中的增强器,并将增强器封装成拦截器链

1 @Override
2 public List<Object>getInterceptorsAndDynamicInterceptionAdvice(
3         Advised config, Method method, @Nullable Class<?>targetClass) {
4 
5     //This is somewhat tricky... We have to process introductions first,
6     //but we need to preserve order in the ultimate list.
7     AdvisorAdapterRegistry registry =GlobalAdvisorAdapterRegistry.getInstance();
8     Advisor[] advisors =config.getAdvisors();
9     List<Object> interceptorList = new ArrayList<>(advisors.length);
10     Class<?> actualClass = (targetClass != null ?targetClass : method.getDeclaringClass());
11     Boolean hasIntroductions = null;
12 
13     //获取bean中的所有增强器
14     for(Advisor advisor : advisors) {
15         if (advisor instanceofPointcutAdvisor) {
16             //Add it conditionally.
17             PointcutAdvisor pointcutAdvisor =(PointcutAdvisor) advisor;
18             if (config.isPreFiltered() ||pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
19                 MethodMatcher mm =pointcutAdvisor.getPointcut().getMethodMatcher();
20                 booleanmatch;
21                 if (mm instanceofIntroductionAwareMethodMatcher) {
22                     if (hasIntroductions == null) {
23                         hasIntroductions =hasMatchingIntroductions(advisors, actualClass);
24 }
25                     match =((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);
26 }
27                 else{
28                   //根据增强器中的Pointcut判断增强器是否能匹配当前类中的method
29                     //我们要知道目标Bean中并不是所有的方法都需要增强,也有一些普通方法
30                     match =mm.matches(method, actualClass);
31 }
32                 if(match) {
33                   //如果能匹配,就将advisor封装成MethodInterceptor加入到interceptorList中
34                     MethodInterceptor[] interceptors =registry.getInterceptors(advisor);
35                     if(mm.isRuntime()) {
36                         //Creating a new object instance in the getInterceptors() method
37                         //isn't a problem as we normally cache created chains.
38                         for(MethodInterceptor interceptor : interceptors) {
39                            interceptorList.add(newInterceptorAndDynamicMethodMatcher(interceptor, mm));
40 }
41 }
42                     else{
43 interceptorList.addAll(Arrays.asList(interceptors));
44 }
45 }
46 }
47 }
48         else if (advisor instanceofIntroductionAdvisor) {
49             IntroductionAdvisor ia =(IntroductionAdvisor) advisor;
50             if (config.isPreFiltered() ||ia.getClassFilter().matches(actualClass)) {
51                 Interceptor[] interceptors =registry.getInterceptors(advisor);
52 interceptorList.addAll(Arrays.asList(interceptors));
53 }
54 }
55         else{
56             Interceptor[] interceptors =registry.getInterceptors(advisor);
57 interceptorList.addAll(Arrays.asList(interceptors));
58 }
59 }
60 
61     returninterceptorList;
62 }

我们知道目标Bean中并不是所有的方法都需要增强,所以我们要遍历所有的Advisor ,根据Pointcut判断增强器是否能匹配当前类中的method,取出能匹配的增强器,封装成MethodInterceptor,加入到拦截器链中,我们来看看第34行

@Override
public MethodInterceptor[] getInterceptors(Advisor advisor) throwsUnknownAdviceTypeException {
    List<MethodInterceptor> interceptors = new ArrayList<>(3);
    Advice advice =advisor.getAdvice();
    if (advice instanceofMethodInterceptor) {
        interceptors.add((MethodInterceptor) advice);
    }
    //这里遍历三个适配器,将对应的advisor转化成Interceptor
    //这三个适配器分别是MethodBeforeAdviceAdapter,AfterReturningAdviceAdapter,ThrowsAdviceAdapter
    for (AdvisorAdapter adapter : this.adapters) {
        if(adapter.supportsAdvice(advice)) {
            interceptors.add(adapter.getInterceptor(advisor));
        }
    }
    if(interceptors.isEmpty()) {
        throw newUnknownAdviceTypeException(advisor.getAdvice());
    }
    return interceptors.toArray(new MethodInterceptor[0]);
}
private final List<AdvisorAdapter> adapters = new ArrayList<>(3);
/**
 * Create a new DefaultAdvisorAdapterRegistry, registering well-known adapters.
 */
publicDefaultAdvisorAdapterRegistry() {
    registerAdvisorAdapter(newMethodBeforeAdviceAdapter());
    registerAdvisorAdapter(newAfterReturningAdviceAdapter());
    registerAdvisorAdapter(newThrowsAdviceAdapter());
}
@Override
public voidregisterAdvisorAdapter(AdvisorAdapter adapter) {
    this.adapters.add(adapter);
}

由于Spring中涉及过多的拦截器,增强器,增强方法等方式来对逻辑进行增强,在上一篇文章中我们知道创建的几个增强器,AspectJAroundAdvice、AspectJAfterAdvice、AspectJAfterThrowingAdvice这几个增强器都实现了MethodInterceptor 接口,AspectJMethodBeforeAdvice 和AspectJAfterReturningAdvice 并没有实现MethodInterceptor 接口,因此AspectJMethodBeforeAdvice 和AspectJAfterReturningAdvice不能满足MethodInterceptor 接口中的invoke方法,所以这里使用适配器模式将AspectJMethodBeforeAdvice 和AspectJAfterReturningAdvice转化成能满足需求的MethodInterceptor实现类。

遍历adapters,通过adapter.supportsAdvice(advice)找到advice对应的适配器,adapter.getInterceptor(advisor)将advisor转化成对应的interceptor

我们来看看这几个增强器

AspectJAroundAdvice

spring5 源码深度解析----- AOP代理的生成第1张spring5 源码深度解析----- AOP代理的生成第2张
public class AspectJAroundAdvice extends AbstractAspectJAdvice implementsMethodInterceptor, Serializable {
    publicAspectJAroundAdvice(
            Method aspectJAroundAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
        super(aspectJAroundAdviceMethod, pointcut, aif);
    }
    @Override
    public booleanisBeforeAdvice() {
        return false;
    }
    @Override
    public booleanisAfterAdvice() {
        return false;
    }
    @Override
    public Object invoke(MethodInvocation mi) throwsThrowable {
        if (!(mi instanceofProxyMethodInvocation)) {
            throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " +mi);
        }
        ProxyMethodInvocation pmi =(ProxyMethodInvocation) mi;
        ProceedingJoinPoint pjp =lazyGetProceedingJoinPoint(pmi);
        JoinPointMatch jpm =getJoinPointMatch(pmi);
        return invokeAdviceMethod(pjp, jpm, null, null);
    }
}
View Code

AspectJMethodBeforeAdvice

spring5 源码深度解析----- AOP代理的生成第1张spring5 源码深度解析----- AOP代理的生成第4张
public class AspectJMethodBeforeAdvice extends AbstractAspectJAdvice implementsMethodBeforeAdvice, Serializable {
    publicAspectJMethodBeforeAdvice(
            Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
        super(aspectJBeforeAdviceMethod, pointcut, aif);
    }
    @Override
    public void before(Method method, Object[] args, @Nullable Object target) throwsThrowable {
        invokeAdviceMethod(getJoinPointMatch(), null, null);
    }
    @Override
    public booleanisBeforeAdvice() {
        return true;
    }
    @Override
    public booleanisAfterAdvice() {
        return false;
    }
}
View Code

AspectJAfterAdvice

spring5 源码深度解析----- AOP代理的生成第1张spring5 源码深度解析----- AOP代理的生成第6张
public class AspectJAfterAdvice extendsAbstractAspectJAdvice
        implementsMethodInterceptor, AfterAdvice, Serializable {
    publicAspectJAfterAdvice(
            Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
        super(aspectJBeforeAdviceMethod, pointcut, aif);
    }
    @Override
    public Object invoke(MethodInvocation mi) throwsThrowable {
        try{
            returnmi.proceed();
        }
        finally{
            invokeAdviceMethod(getJoinPointMatch(), null, null);
        }
    }
    @Override
    public booleanisBeforeAdvice() {
        return false;
    }
    @Override
    public booleanisAfterAdvice() {
        return true;
    }
}
View Code

AspectJAfterReturningAdvice

spring5 源码深度解析----- AOP代理的生成第1张spring5 源码深度解析----- AOP代理的生成第8张
public class AspectJAfterReturningAdvice extendsAbstractAspectJAdvice
        implementsAfterReturningAdvice, AfterAdvice, Serializable {
    publicAspectJAfterReturningAdvice(
            Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
        super(aspectJBeforeAdviceMethod, pointcut, aif);
    }
    @Override
    public booleanisBeforeAdvice() {
        return false;
    }
    @Override
    public booleanisAfterAdvice() {
        return true;
    }
    @Override
    public void afterReturning(@Nullable Object returnValue, Method method, Object[] args, @Nullable Object target) throwsThrowable {
        if(shouldInvokeOnReturnValueOf(method, returnValue)) {
            invokeAdviceMethod(getJoinPointMatch(), returnValue, null);
        }
    }
}
View Code

AspectJAfterThrowingAdvice

spring5 源码深度解析----- AOP代理的生成第1张spring5 源码深度解析----- AOP代理的生成第10张
public class AspectJAfterThrowingAdvice extendsAbstractAspectJAdvice
        implementsMethodInterceptor, AfterAdvice, Serializable {
    publicAspectJAfterThrowingAdvice(
            Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
        super(aspectJBeforeAdviceMethod, pointcut, aif);
    }
    @Override
    public booleanisBeforeAdvice() {
        return false;
    }
    @Override
    public booleanisAfterAdvice() {
        return true;
    }
    @Override
    public Object invoke(MethodInvocation mi) throwsThrowable {
        try{
            returnmi.proceed();
        }
        catch(Throwable ex) {
            if(shouldInvokeOnThrowing(ex)) {
                invokeAdviceMethod(getJoinPointMatch(), null, ex);
            }
            throwex;
        }
    }
}
View Code

接下来我们看看MethodBeforeAdviceAdapter和AfterReturningAdviceAdapter这两个适配器,这两个适配器是将MethodBeforeAdvice和AfterReturningAdvice适配成对应的Interceptor

MethodBeforeAdviceAdapter

class MethodBeforeAdviceAdapter implementsAdvisorAdapter, Serializable {
    @Override
    public booleansupportsAdvice(Advice advice) {
        //判断是否是MethodBeforeAdvice类型的advice
        return (advice instanceofMethodBeforeAdvice);
    }
    @Override
    publicMethodInterceptor getInterceptor(Advisor advisor) {
        MethodBeforeAdvice advice =(MethodBeforeAdvice) advisor.getAdvice();
        //将advice封装成MethodBeforeAdviceInterceptor
        return newMethodBeforeAdviceInterceptor(advice);
    }
}
//MethodBeforeAdviceInterceptor实现了MethodInterceptor接口,实现了invoke方法,并将advice作为属性
public class MethodBeforeAdviceInterceptor implementsMethodInterceptor, BeforeAdvice, Serializable {
    private finalMethodBeforeAdvice advice;
    publicMethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
        Assert.notNull(advice, "Advice must not be null");
        this.advice =advice;
    }
    @Override
    public Object invoke(MethodInvocation mi) throwsThrowable {
        this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
        returnmi.proceed();
    }
}

AfterReturningAdviceAdapter

class AfterReturningAdviceAdapter implementsAdvisorAdapter, Serializable {
    @Override
    public booleansupportsAdvice(Advice advice) {
        return (advice instanceofAfterReturningAdvice);
    }
    @Override
    publicMethodInterceptor getInterceptor(Advisor advisor) {
        AfterReturningAdvice advice =(AfterReturningAdvice) advisor.getAdvice();
        return newAfterReturningAdviceInterceptor(advice);
    }
}
public class AfterReturningAdviceInterceptor implementsMethodInterceptor, AfterAdvice, Serializable {
    private finalAfterReturningAdvice advice;
    publicAfterReturningAdviceInterceptor(AfterReturningAdvice advice) {
        Assert.notNull(advice, "Advice must not be null");
        this.advice =advice;
    }
    @Override
    public Object invoke(MethodInvocation mi) throwsThrowable {
        Object retVal =mi.proceed();
        this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
        returnretVal;
    }
}

至此我们获取到了一个拦截器链,链中包括AspectJAroundAdvice、AspectJAfterAdvice、AspectJAfterThrowingAdvice、MethodBeforeAdviceInterceptor、AfterReturningAdviceInterceptor

接下来ReflectiveMethodInvocation 类进行了链的封装,而在ReflectiveMethodInvocation类的proceed方法中实现了拦截器的逐一调用,那么我们继续来探究,在proceed方法中是怎么实现前置增强在目标方法前调用后置增强在目标方法后调用的逻辑呢?

我们先来看看ReflectiveMethodInvocation的构造器,只是简单的进行属性赋值,不过我们要注意有一个特殊的变量currentInterceptorIndex,这个变量代表执行Interceptor的下标,从-1开始,Interceptor执行一个,先++this.currentInterceptorIndex

protectedReflectiveMethodInvocation(
        Object proxy, @Nullable Object target, Method method, @Nullable Object[] arguments,
        @Nullable Class<?> targetClass, List<Object>interceptorsAndDynamicMethodMatchers) {
    this.proxy =proxy;
    this.target =target;
    this.targetClass =targetClass;
    this.method =BridgeMethodResolver.findBridgedMethod(method);
    this.arguments =AopProxyUtils.adaptArgumentsIfNecessary(method, arguments);
    this.interceptorsAndDynamicMethodMatchers =interceptorsAndDynamicMethodMatchers;
}
private int currentInterceptorIndex = -1;

下面是ReflectiveMethodInvocation类Proceed方法:

public Object proceed() throwsThrowable {
    //首先,判断是不是所有的interceptor(也可以想像成advisor)都被执行完了。
    //判断的方法是看currentInterceptorIndex这个变量的值,增加到Interceptor总个数这个数值没有,
    //如果到了,就执行被代理方法(invokeJoinpoint());如果没到,就继续执行Interceptor。
    if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
        returninvokeJoinpoint();
    }
    //如果Interceptor没有被全部执行完,就取出要执行的Interceptor,并执行。
    //currentInterceptorIndex先自增
    Object interceptorOrInterceptionAdvice =this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
    //如果Interceptor是PointCut类型
    if (interceptorOrInterceptionAdvice instanceofInterceptorAndDynamicMethodMatcher) {
        InterceptorAndDynamicMethodMatcher dm =(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
        //如果当前方法符合Interceptor的PointCut限制,就执行Interceptor
        if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
           //这里将this当变量传进去,这是非常重要的一点
            return dm.interceptor.invoke(this);
        }
        //如果不符合,就跳过当前Interceptor,执行下一个Interceptor
        else{
            returnproceed();
        }
    }
    //如果Interceptor不是PointCut类型,就直接执行Interceptor里面的增强。
    else{
        return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
    }
}

由于篇幅过程,目标方法和增强方法是如何执行的,我们将重新写一篇文章来讲解

免责声明:文章转载自《spring5 源码深度解析----- AOP代理的生成》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Java运行时栈帧结构三、文件的操作、函数、类和对象下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Spring Boot源码(一)Spring Boot源码环境搭建

一、前言   既然要分析源码,那就直接下载源码来本地运行分析,是最有效的方案,但是在开始看这篇博客之前,希望小伙伴们有个心理准备...   源码编译是比较麻烦的一件事,我大概整了一天才基本整好源码环境,期间可能遇到各种奇奇怪怪的问题上网找答案,这里把流程记录一下,需要的小伙伴可以直接跟着步骤走,还是可以顺利编译通过的,亲测可行。 二、源码环境搭建 下载源码...

java 根据实体对象生成 增删改的SQL语句 ModelToSQL

package com.xxx.utils; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.List; import java.util.Vector; import org.apache.commons.lang3....

理解Android编译命令(转)

一、引言 关于Android Build系统,这个话题很早就打算整理下,迟迟没有下笔,决定跟大家分享下。先看下面几条指令,相信编译过Android源码的人都再熟悉不过的。 source setenv.sh lunch make -j12 记得最初刚接触Android时,同事告诉我用上面的指令就可以编译Android源码,指令虽短但过几天就记不全或者忘记...

nginx使用:正向代理、反向代理、负载均衡。常用命令和配置文件

文章目录前言 原文地址→→ 一、nginx简介 1. 什么是 nginx 和可以做什么事情 2.Nginx 作为 web 服务器 3. 正向代理 4. 反向代理 5. 负载均衡 6.动静分离 二、Nginx 的安装(Linux:centos为例)1. 准备工作2. 开始安装3. 运行nginx4. 防火墙问题 三、 Nginx 的常用命令和配置文件 1....

如何阅读jdk源码?

简介 这篇文章主要讲述jdk本身的源码该如何阅读,关于各种框架的源码阅读我们后面再一起探讨。 笔者认为阅读源码主要包括下面几个步骤。 设定目标 凡事皆有目的,阅读源码也是一样。 从大的方面来说,我们阅读源码的目的是为了提升自己的技术能力,运用到工作中,遇到问题快速定位,升职加薪等等。 从小的方面来说,阅读某一段源码的目的就是要搞清楚它的原理,就是死磕,就是...

element dropdown源码

dropdown.vue <script>import Clickoutside from 'element-ui/src/utils/clickoutside'; import Emitter from 'element-ui/src/mixins/emitter'; import Migrating from 'element-ui...