紧接着上文,在获取了所有对应 Bean 的增强器后,便可以进行代理的创建了。
回到 postProcesssAfterIntialization 方法中,在我们分析完 getAdvicesAndAdvisorsForBean()
后,还有一个 createProxy 方法。
protected Object createProxy(Class<?> beanClass, @Nullable String beanName, @Nullable Object[] specificInterceptors, TargetSource targetSource) { if (this.beanFactory instanceof ConfigurableListableBeanFactory) { //指定自动代理Bean的原始目标类 AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory)this.beanFactory, beanName, beanClass); } ProxyFactory proxyFactory = new ProxyFactory(); //获取当前类中相关属性 proxyFactory.copyFrom(this); if (!proxyFactory.isProxyTargetClass()) { // 决定对于给定的bean是否应该使用targetClass而不是它的接口代理, // 检査 proxyTargetClass 设置以及 preserveTargetClass 属性 if (this.shouldProxyTargetClass(beanClass, beanName)) { proxyFactory.setProxyTargetClass(true); } else { this.evaluateProxyInterfaces(beanClass, proxyFactory); } } Advisor[] advisors = this.buildAdvisors(beanName, specificInterceptors); // 加入增强器 proxyFactory.addAdvisors(advisors); // 设置要代理的目标类 proxyFactory.setTargetSource(targetSource); // 定制代理 this.customizeProxyFactory(proxyFactory); // 用来控制代理工厂被配置之后,是否还允许修改通知。 // 缺省值是false (即在代理被配置之后,不允许修改代理的配置)。 proxyFactory.setFrozen(this.freezeProxy); if (this.advisorsPreFiltered()) { proxyFactory.setPreFiltered(true); } //真正创建代理的方法 return proxyFactory.getProxy(this.getProxyClassLoader()); } 复制代码
对于代理类的创建及处理,Spring 委托给了 ProxyFactory 去处理,而在此函数中主要是对 ProxyFactory 的初始化操作,进而对真正的创建代理做准备,这些初始化操作包括以下内容:
- 获取当前类中的属性。
- 添加代理接口。
- 封装 Advisor 并加入到 ProxyFactory 中。
- 设置要代理的类。
- customizeProxyFactory 函数定制代理。
- 进行获取代理操作。
封装 Advisor
其中,封装 Advisor 并加入到 ProxyFactory 中以及创建代理工作量比较大,所以我们就来看一下 buildAdvisors()
。
protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) { Advisor[] commonInterceptors = this.resolveInterceptorNames(); List<Object> allInterceptors = new ArrayList(); if (specificInterceptors != null) { allInterceptors.addAll(Arrays.asList(specificInterceptors)); if (commonInterceptors.length > 0) { if (this.applyCommonInterceptorsFirst) { allInterceptors.addAll(0, Arrays.asList(commonInterceptors)); } else { allInterceptors.addAll(Arrays.asList(commonInterceptors)); } } } int i; if (this.logger.isTraceEnabled()) { int nrOfCommonInterceptors = commonInterceptors.length; i = specificInterceptors != null ? specificInterceptors.length : 0; this.logger.trace("Creating implicit proxy for bean '" + beanName + "' with " + nrOfCommonInterceptors + " common interceptors and " + i + " specific interceptors"); } Advisor[] advisors = new Advisor[allInterceptors.size()]; for(i = 0; i < allInterceptors.size(); ++i) { advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i)); } return advisors; } 复制代码
上述方法中会涉及到适配器模式的应用,我们转到 DefaultAdvisorAdapterRegistry 类中,查看其 wrap 方法。
public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException { if (adviceObject instanceof Advisor) { return (Advisor)adviceObject; } else if (!(adviceObject instanceof Advice)) { throw new UnknownAdviceTypeException(adviceObject); } else { Advice advice = (Advice)adviceObject; if (advice instanceof MethodInterceptor) { //如果是MethodInterceptor类型,则封装为DefaultPointcutAdvisor return new DefaultPointcutAdvisor(advice); } else { Iterator var3 = this.adapters.iterator(); //如果存在Advisor的适配器则也需要进行封装 AdvisorAdapter adapter; do { if (!var3.hasNext()) { throw new UnknownAdviceTypeException(advice); } adapter = (AdvisorAdapter)var3.next(); } while(!adapter.supportsAdvice(advice)); return new DefaultPointcutAdvisor(advice); } } } 复制代码
关于这一部分,我进行了调试追踪,发现该方法的结果如下:
对此我有一个疑问:在创建代理之前,即执行 getAdvicesAndAdvisorsForBean()
方法后,我们获取到的结果除了头部对象是 DefaultPointcutAdvisor 类型,其他三个是 Advisor 的实现类 InstantiationModelAwarePointcutAdvisorImpl 类型,执行 wrap 方法中 adviceObject instanceof Advisor
结果都为 true。那么该方法主要是针对什么情景下使用的呢?如果有大神知晓,请不吝赐教。
创建代理
封装完 Advisor 之后就准备进行代理的创建,这也是解析过程中最重要的一步。
public Object getProxy(@Nullable ClassLoader classLoader) { return this.createAopProxy().getProxy(classLoader); } 复制代码
在上面的 getProxy 方法中 createAopProxy 方法,其实现是在 ProxyCreatorSupport 中,其定义如下:
protected final synchronized AopProxy createAopProxy() { if (!this.active) { this.activate(); } return this.getAopProxyFactory().createAopProxy(this); } private void activate() { this.active = true; Iterator var1 = this.listeners.iterator(); while(var1.hasNext()) { //启动监听器 AdvisedSupportListener listener = (AdvisedSupportListener)var1.next(); listener.activated(this); } } 复制代码
再次跳转到 DefaultAopProxyFactory 类中,查看 createAopProxy 方法。
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { if (!config.isOptimize() && !config.isProxyTargetClass() && !this.hasNoUserSuppliedProxyInterfaces(config)) { return new JdkDynamicAopProxy(config); } else { 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."); } else { //手动设置创建Cglib代理类后,如果目标bean是一个接口,则创建jdk代理类 return (AopProxy)(!targetClass.isInterface() && !Proxy.isProxyClass(targetClass) ? new ObjenesisCglibAopProxy(config) : new JdkDynamicAopProxy(config)); } } } 复制代码
我们在 代理模式一文中知道 Spring 的代理是通过 JDKProxy 的实现或 CglibProxy 实现。Spring 是如何选取的呢?
从 if 中的判断条件可以看到3个方面影响着 Spring 的判断。
- optimize:用来控制通过CGLIB创建的代理是否使用激进的优化策略,除非完全了解AOP代理如何处理优化,否则不推荐用户使用这个设置。目前这个属性仅用于CGLIB 代理,对于JDK动态代理(缺省代理)无效。
- proxyTargetClass:这个属性为true时,目标类本身被代理而不是目标类的接口。如果这个属性值被设为true,CGLIB代理将被创建,设置方式:。
- hasNoUserSuppliedProxylnterfaces:是否存在代理接口
下面是对JDK与Cglib方式的总结。
- 如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP。
- 如果目标对象实现了接口,可以强制使用CGLIB实现AOP。
- 如果目标对象没有实现了接口,必须采用CGLIB库,Spring会自动在JDK动态代理 和CGLIB之间转换。
如何强制使用CGLIB实现AOP?
(1)添加 CGLIB 库,Spring_HOME/cglib/*.jar。
(2)在 Spring 配置文件中加人。
JDK 动态代理和 CGLIB 字节码生成的区别?
JDK 动态代理只能对实现了接口的类生成代理,而不能针对类。
CGLIB 是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法,因为是继承,所以该类或方法最好不要声明成 final。
获取代理
本文主要介绍 JDK 动态代理类的实现,在此之前,有必要熟悉一下 JDK 代理使用示例,请看我以前的博文 代理模式。
Spring 的 AOP 实现其实也是用了 Proxy和InvocationHandler 这两个东西的。
我们再次来回顾一下使用 JDK 代理的方式,在整个创建过程中,对于 InvocationHandler 的创建是最为核心的,关于 Proxy 的获取方法其实也可以放在 InvocationHandler 的实现类中。这样总结为3个函数:
- 构造函数,传入代理的对象。
- invoke 方法,此方法用于实现 AOP 增强的所有逻辑。
- getProxy 方法,即
Proxy.newProxyInstance()
方法,必不可少。
接下来我们学习一下 JdkDynamicAopProxy 的源码。
public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException { Assert.notNull(config, "AdvisedSupport must not be null"); if (config.getAdvisors().length == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) { throw new AopConfigException("No advisors and no TargetSource specified"); } else { this.advised = config; } } public Object getProxy() { return this.getProxy(ClassUtils.getDefaultClassLoader()); } public Object getProxy(@Nullable ClassLoader classLoader) { if (logger.isTraceEnabled()) { logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource()); } Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true); this.findDefinedEqualsAndHashCodeMethods(proxiedInterfaces); return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this); } private void findDefinedEqualsAndHashCodeMethods(Class<?>[] proxiedInterfaces) { Class[] var2 = proxiedInterfaces; int var3 = proxiedInterfaces.length; for(int var4 = 0; var4 < var3; ++var4) { Class<?> proxiedInterface = var2[var4]; Method[] methods = proxiedInterface.getDeclaredMethods(); Method[] var7 = methods; int var8 = methods.length; for(int var9 = 0; var9 < var8; ++var9) { Method method = var7[var9]; if (AopUtils.isEqualsMethod(method)) { this.equalsDefined = true; } if (AopUtils.isHashCodeMethod(method)) { this.hashCodeDefined = true; } if (this.equalsDefined && this.hashCodeDefined) { return; } } } } @Nullable public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object oldProxy = null; boolean setProxyContext = false; TargetSource targetSource = this.advised.targetSource; Object target = null; Integer var8; try { //equals方法判断 if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) { Boolean var18 = this.equals(args[0]); return var18; } //hash方法判断 if (this.hashCodeDefined || !AopUtils.isHashCodeMethod(method)) { if (method.getDeclaringClass() == DecoratingProxy.class) { Class var17 = AopProxyUtils.ultimateTargetClass(this.advised); return var17; } Object retVal; if (!this.advised.opaque && method.getDeclaringClass().isInterface() && method.getDeclaringClass().isAssignableFrom(Advised.class)) { retVal = AopUtils.invokeJoinpointUsingReflection(this.advised, method, args); return retVal; } // 如果 expose-proxy 属性为 true,则暴露代理对象 if (this.advised.exposeProxy) { oldProxy = AopContext.setCurrentProxy(proxy); setProxyContext = true; } target = targetSource.getTarget(); Class<?> targetClass = target != null ? target.getClass() : null; // 获取适合当前方法的拦截器 List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); if (chain.isEmpty()) {// 如果拦截器链为空,则直接执行目标方法 Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args); // 通过反射执行目标方法 retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse); } else { // 创建一个方法调用器,并将拦截器链传入其中 MethodInvocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain); // 执行拦截器链 retVal = invocation.proceed(); } // 获取方法返回值类型 Class<?> returnType = method.getReturnType(); if (retVal != null && retVal == target && returnType != Object.class && returnType.isInstance(proxy) && !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) { // 如果方法返回值为 this,即 return this; 则将代理对象 proxy 赋值给 retVal retVal = proxy; } else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) { // 如果返回值类型为基础类型,比如 int,long 等,当返回值为 null,抛出异常 throw new AopInvocationException("Null return value from advice does not match primitive return type for: " + method); } Object var12 = retVal; return var12; } var8 = this.hashCode(); } finally { if (target != null && !targetSource.isStatic()) { targetSource.releaseTarget(target); } if (setProxyContext) { AopContext.setCurrentProxy(oldProxy); } } return var8; } 复制代码
我们总结一下 invoke 方法的执行流程,如下:
- 检测 expose-proxy 是否为true,若为true,则暴露代理对象。
- 获取适合当前方法的拦截器。
- 如果拦截器链为空,则直接通过反射执行目标方法。
- 如果拦截器链不为空,则创建 ReflectiveMethodInvocation 对象。
- 调用 ReflectiveMethodInvocation 对象的 proceed()方法启动拦截器链。
- 处理返回值,并返回该值。
以上六个步骤,我们重点关注第2步和第5步的处理逻辑,下面先来分析获取拦截器链的过程。
获取目标方法的拦截器
getInterceptorsAndDynamicInterceptionAdvice()
方法用来获取目标方法的拦截器,这是我们在 Spring AOP 中第一次提到拦截器,大家可能在别的地方使用过,拦截器用于对目标方法的调用进行拦截的一种工具。拦截器与我们之前获取的增强器有什么关系呢?带着这样的疑问,我们来分析 AdvisedSupport 类中的 getInterceptorsAndDynamicInterceptionAdvice 源码。
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) { AdvisedSupport.MethodCacheKey cacheKey = new AdvisedSupport.MethodCacheKey(method); // 从缓存中获取 List<Object> cached = (List)this.methodCache.get(cacheKey); // 缓存为空,则进行下一步处理 if (cached == null) { // 获取所有的拦截器 cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(this, method, targetClass); // 存入缓存 this.methodCache.put(cacheKey, cached); } return cached; } 复制代码
其中比较核心的方法是 getInterceptorsAndDynamicInterceptionAdvice()
,在 DefaultAdvisorChainFactory 类中实现。
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Advised config, Method method, @Nullable Class<?> targetClass) { // registry 为 DefaultAdvisorAdapterRegistry 类型 AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance(); //获取目标方法对应的增强器 Advisor[] advisors = config.getAdvisors(); //声明拦截器列表 List<Object> interceptorList = new ArrayList(advisors.length); //目标类 Class<?> actualClass = targetClass != null ? targetClass : method.getDeclaringClass(); Boolean hasIntroductions = null; Advisor[] var9 = advisors; int var10 = advisors.length; // 遍历增强器列表 for(int var11 = 0; var11 < var10; ++var11) { Advisor advisor = var9[var11]; if (advisor instanceof PointcutAdvisor) { PointcutAdvisor pointcutAdvisor = (PointcutAdvisor)advisor; //调用 ClassFilter 对 bean 类型进行匹配,无法匹配则说明当前增强器不适用于当前bean if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) { MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher(); boolean match; // 通过方法匹配器对目标方法进行匹配 if (mm instanceof IntroductionAwareMethodMatcher) { if (hasIntroductions == null) { hasIntroductions = hasMatchingIntroductions(advisors, actualClass); } match = ((IntroductionAwareMethodMatcher)mm).matches(method, actualClass, hasIntroductions); } else { match = mm.matches(method, actualClass); } if (match) { // 将 advisor 中的 advice 转成相应的拦截器 MethodInterceptor[] interceptors = registry.getInterceptors(advisor); // 若 isRuntime 返回 true,则表明 MethodMatcher 要在运行时做一些检测 if (mm.isRuntime()) { MethodInterceptor[] var17 = interceptors; int var18 = interceptors.length; for(int var19 = 0; var19 < var18; ++var19) { MethodInterceptor interceptor = var17[var19]; interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm)); } } else { interceptorList.addAll(Arrays.asList(interceptors)); } } } } else if (advisor instanceof IntroductionAdvisor) { IntroductionAdvisor ia = (IntroductionAdvisor)advisor; // IntroductionAdvisor 类型的增强器,仅需进行类级别的匹配即可 if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) { Interceptor[] interceptors = registry.getInterceptors(advisor); interceptorList.addAll(Arrays.asList(interceptors)); } } else { Interceptor[] interceptors = registry.getInterceptors(advisor); interceptorList.addAll(Arrays.asList(interceptors)); } } return interceptorList; } public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException { List<MethodInterceptor> interceptors = new ArrayList(3); Advice advice = advisor.getAdvice(); //若 advice 是 MethodInterceptor 类型的,直接添加到 interceptors 中即可 //比如 AspectJAfterAdvice 就实现了 MethodInterceptor 接口 if (advice instanceof MethodInterceptor) { interceptors.add((MethodInterceptor)advice); } Iterator var4 = this.adapters.iterator(); //对于 AspectJMethodBeforeAdvice 等类型的通知,由于没有实现 MethodInterceptor接口,所以这里需要通过适配器进行转换 //比如AspectJMethodBeforeAdvice类型会被转换为MethodBeforeAdviceInterceptor while(var4.hasNext()) { AdvisorAdapter adapter = (AdvisorAdapter)var4.next(); if (adapter.supportsAdvice(advice)) { interceptors.add(adapter.getInterceptor(advisor)); } } if (interceptors.isEmpty()) { throw new UnknownAdviceTypeException(advisor.getAdvice()); } else { return (MethodInterceptor[])interceptors.toArray(new MethodInterceptor[0]); } } 复制代码
以上便是获取拦截器的过程,不过好在逻辑不是很复杂,这里简单总结一下。
- 从缓存中获取目标方法的拦截器链。
- 若缓存为中,则调用 getInterceptorsAndDynamicInterceptionAdvice 获取拦截器链。
- 遍历增强器列表,如果是 PointcutAdvisor 类型的增强器,需要调用增强器所持有的切点对类和方法进行匹配,匹配成功说明应向当前方法织入通知逻辑卷。
- 调用 getInterceptors 方法对非 MethodInterceptor 类型的通知转换为拦截器。
- 返回拦截器链,并存入缓存中。
由于 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。
比如 AspectJMethodBeforeAdvice ,我们查看一下其对应的拦截器。
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice, Serializable { private final MethodBeforeAdvice advice; public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) { Assert.notNull(advice, "Advice must not be null"); this.advice = advice; } public Object invoke(MethodInvocation mi) throws Throwable { //执行前置通知逻辑 this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis()); //调用proceed执行下一个拦截器 return mi.proceed(); } } 复制代码
代码比较简单,这里就不多说了。
现在我们已经获得了拦截器链,那么接下来要做的就是启动拦截器,我们继续向下分析代码,看看 Spring 是如何启动拦截器链的。
启动拦截器链
回到 JdkDynamicAopProxy 中,继续向下学习。我们先来说说 ReflectiveMethodInvocation,该类贯穿于拦截器链执行的始终,是非常核心的内容。该类的 proceed 方法用于启动拦截器链,下面我们看下该方法。
public Object proceed() throws Throwable { //判断是不是所有的interceptor(也可以想像成advisor)都被执行完了。 // 拦截器链中的最后一个拦截器执行完后,即可执行目标方法 if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) { return this.invokeJoinpoint(); } else { // 如果Interceptor没有被全部执行完,就取出要执行的Interceptor,并执行。 // currentInterceptorIndex先自增 Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex); // 如果Interceptor是PointCut类型 if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) { InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher)interceptorOrInterceptionAdvice; Class<?> targetClass = this.targetClass != null ? this.targetClass : this.method.getDeclaringClass(); // 如果当前方法符合Interceptor的PointCut限制,就执行Interceptor,如果不符合,则跳过并执行下一个Interceptor return dm.methodMatcher.matches(this.method, targetClass, this.arguments) ? dm.interceptor.invoke(this) : this.proceed(); } else { // 如果Interceptor不是PointCut类型,就直接执行Interceptor里面的增强。 return ((MethodInterceptor)interceptorOrInterceptionAdvice).invoke(this); } } } 复制代码
从上述代码可知,ReflectiveMethodInvocation 中的 currentInterceptorIndex 充当拦截器链调用的计数器,记录着当前调用链接的位置 proceed 根据 currentInterceptorIndex 来确定当前应执行哪个拦截器,并在调用拦截器的 invoke 方法时,将自己作为参数传给该方法。 前置通知会在目标方法执行前执行,我们在前面也看了前置拦截器的源码,这里看一下后置拦截器的源码,如下:
public class AspectJAfterAdvice extends AbstractAspectJAdvice implements MethodInterceptor, AfterAdvice, Serializable { public AspectJAfterAdvice(Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) { super(aspectJBeforeAdviceMethod, pointcut, aif); } public Object invoke(MethodInvocation mi) throws Throwable { Object var2; try { var2 = mi.proceed(); } finally { //调用后置通知逻辑 this.invokeAdviceMethod(this.getJoinPointMatch(), (Object)null, (Throwable)null); } return var2; } public boolean isBeforeAdvice() { return false; } public boolean isAfterAdvice() { return true; } } 复制代码
因为后置通知是在目标方法返回后执行,所以 AspectJAfterAdvice 先调用 mi.proceed()
执行下一个拦截器逻辑,等下一个拦截器返回后,最后执行后置通知逻辑。如果大家不理解,我根据调试过程画了一张图,结合初识Spring AOP一文中的案例,其中包含前置通知、后置通知和环绕通知,执行流程如下:
关于执行过程中第一个拦截器 ExposeInvocationInterceptor,需要讲解一下。在Spring AOP创建代理之获取增强器文章末尾中,在介绍 extendAdvisors 方法时,有提及到拓展增强器列表,具体意图当时没有讲述,待会进行补充说明。这里再贴一下 extendAdvisors 方法的源码,如下:
protected void extendAdvisors(List<Advisor> candidateAdvisors) { AspectJProxyUtils.makeAdvisorChainAspectJCapableIfNecessary(candidateAdvisors); } public static boolean makeAdvisorChainAspectJCapableIfNecessary(List<Advisor> advisors) { if (!advisors.isEmpty()) { boolean foundAspectJAdvice = false; Iterator var2 = advisors.iterator(); while(var2.hasNext()) { Advisor advisor = (Advisor)var2.next(); //检测 advisors 列表中是否存在 AspectJ 类型的 Advisor 或 Advice if (isAspectJAdvice(advisor)) { foundAspectJAdvice = true; break; } } if (foundAspectJAdvice && !advisors.contains(ExposeInvocationInterceptor.ADVISOR)) { //向 advisors 列表的首部添加 ExposeInvocationInterceptor.ADVISOR advisors.add(0, ExposeInvocationInterceptor.ADVISOR); return true; } } return false; } 复制代码
如上,extendAdvisors 所调用的方法会向通知器列表首部添加 ExposeInvocationInterceptor.ADVISOR。现在我们再来看看 ExposeInvocationInterceptor 的源码,如下:
public final class ExposeInvocationInterceptor implements MethodInterceptor, PriorityOrdered, Serializable { public static final ExposeInvocationInterceptor INSTANCE = new ExposeInvocationInterceptor(); public static final Advisor ADVISOR; private static final ThreadLocal<MethodInvocation> invocation; public static MethodInvocation currentInvocation() throws IllegalStateException { MethodInvocation mi = (MethodInvocation)invocation.get(); if (mi == null) { throw new IllegalStateException("No MethodInvocation found: Check that an AOP invocation is in progress, and that the ExposeInvocationInterceptor is upfront in the interceptor chain. Specifically, note that advices with order HIGHEST_PRECEDENCE will execute before ExposeInvocationInterceptor!"); } else { return mi; } } private ExposeInvocationInterceptor() { } public Object invoke(MethodInvocation mi) throws Throwable { MethodInvocation oldInvocation = (MethodInvocation)invocation.get(); // 将 mi 设置到 ThreadLocal 中 invocation.set(mi); Object var3; try { var3 = mi.proceed(); } finally { invocation.set(oldInvocation); } return var3; } public int getOrder() { return -2147483647; } private Object readResolve() { return INSTANCE; } static { // 创建 DefaultPointcutAdvisor 匿名对象 ADVISOR = new DefaultPointcutAdvisor(INSTANCE) { public String toString() { return ExposeInvocationInterceptor.class.getName() + ".ADVISOR"; } }; invocation = new NamedThreadLocal("Current AOP method invocation"); } } 复制代码
如上,ExposeInvocationInterceptor.ADVISOR 经过 registry.getInterceptors()
方法(前面已分析过)处理后,即可得到 ExposeInvocationInterceptor。ExposeInvocationInterceptor 的作用是用于暴露 MethodInvocation 对象到 ThreadLocal 中,其名字也体现出了这一点。
关于拦截器链的执行流程,其实可以看成是一个递归的调用过程,通过 ReflectiveMethodInvocation 类中 Proceed 方法递归调用,顺序执行拦截器链中 AspectJAfterAdvice、 AspectJAroundAdvice 、 MethodBeforeAdviceInterceptor这几个拦截器,在拦截器中反射调用通知方法。说的再多,不如实际调试理解的透彻,建议不懂的朋友将这几个拦截器中的 invoke 方法都打上断点,自己亲自执行一遍。
最后说一下目标方法的执行,看一看发生在何处。
执行目标方法
在 proceed 方法中当 currentInterceptorIndex 计数满足条件时,将会执行 invokeJoinpoint 方法,即执行目标方法。我们来看一下源码。
protected Object invokeJoinpoint() throws Throwable { return AopUtils.invokeJoinpointUsingReflection(this.target, this.method, this.arguments); } public static Object invokeJoinpointUsingReflection(@Nullable Object target, Method method, Object[] args) throws Throwable { try { ReflectionUtils.makeAccessible(method); return method.invoke(target, args); } catch (InvocationTargetException var4) { throw var4.getTargetException(); } catch (IllegalArgumentException var5) { throw new AopInvocationException("AOP configuration seems to be invalid: tried calling method [" + method + "] on target [" + target + "]", var5); } catch (IllegalAccessException var6) { throw new AopInvocationException("Could not access method [" + method + "]", var6); } } 复制代码
目标方法就是通过反射执行的,比较简单,在调试的过程中也可以发现。
总结
至此,关于 Spring AOP 源码的学习终于要结束了,关于 Spring 源码的学习大概花了40天的时间,进度比较慢,为此也没怎么学习别的事情。不过结局是好的,通过这次学习还是有很大的收获和成就感。由于技术尚浅,某些部分讲的不够透彻,或者有问题的,请大家见谅,如果可以的话希望能够指正一下,这里先说声谢谢啦。