在getPointcut中解析了method,以及切点表达式pointcut
/** * 找到候选方法method属于哪一种类型的Aspectj通知 * @param candidateAdviceMethod 候选的通知方法 * @param candidateAspectClass 候选的切面类 * @return */ @Nullable private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) { // 第一步: 解析候选方法上的注解,类似@Before(value="pointcut()") // 找到Aspectj注解: @Pointcut, @Around, @Before, @After, @AfterReturning, @AfterThrowing AspectJAnnotation<?> aspectJAnnotation = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod); if (aspectJAnnotation == null) { return null; } // 第二步: 解析aspect切面中的切点表达式 AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]); // 解析切点表达式 ajexp.setExpression(aspectJAnnotation.getPointcutExpression()); if (this.beanFactory != null) { ajexp.setBeanFactory(this.beanFactory); } return ajexp; }
如上代码, 可知, 这里也是有两个操作. 分别是将method解析为Advise, 另一个是解析切面类中的pointcut切点表达式. 返回返回切点表达式.
接下来, 就是将候选方法和切点表达式封装成Advisor. 在getAdvisor(...)方法中:
// 将切点表达式和通知封装到InstantiationModelAwarePointcutAdvisorImpl对象中, 这是一个Advisor通知 return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod, this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
expressionPointcut: 即切点表达式; candidateAdviceMethod: 即候选方法
public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut, Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory, MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) { // 当前的切点 this.declaredPointcut = declaredPointcut; // 切面类 this.declaringClass = aspectJAdviceMethod.getDeclaringClass(); // 切面方法名 this.methodName = aspectJAdviceMethod.getName(); //切面方法参数的类型 this.parameterTypes = aspectJAdviceMethod.getParameterTypes(); //切面方法对象 this.aspectJAdviceMethod = aspectJAdviceMethod; // aspectJ的通知工厂 this.aspectJAdvisorFactory = aspectJAdvisorFactory; // aspectJ的实例工厂 this.aspectInstanceFactory = aspectInstanceFactory; // advisor的顺序 /** * 前面我们看到, Advisor会进行排序, Around, Before, After, AfterReturning, AfterThrowing, 按照这个顺序. * 那么order值是什么呢?是advisors的size. 如果size是0, 那么就是第一个方法. 这里第一个不一定是Around, 他可能没有Around通知, 也没有Before通知. */ this.declarationOrder = declarationOrder; // 切面名 this.aspectName = aspectName; if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) { // Static part of the pointcut is a lazy type. Pointcut preInstantiationPointcut = Pointcuts.union( aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut); this.pointcut = new PerTargetInstantiationModelPointcut( this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory); this.lazy = true; } else { // A singleton aspect. this.pointcut = this.declaredPointcut; this.lazy = false; this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut); } }
前面已经得到了切入点表达式, 这里会进行初始化Advice, 初始化的时候, 根据通知的类型进行初始化.
- 环绕通知, 构建一个环绕通知的对象
- 前置通知, 构建一个前置通知的对象
- 后置通知, 构建一个后置通知的对象
- 异常通知, 构建一个异常通知的对象
- 返回通知, 构建一个返回通知的对象
具体代码如下:
@Override @Nullable public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut, MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) { // 候选的切面类 Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass(); validate(candidateAspectClass); // 通知方法上的注解内容 AspectJAnnotation<?> aspectJAnnotation = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod); if (aspectJAnnotation == null) { return null; } // If we get here, we know we have an AspectJ method. // Check that it's an AspectJ-annotated class if (!isAspect(candidateAspectClass)) { throw new AopConfigException("Advice must be declared inside an aspect type: " + "Offending method '" + candidateAdviceMethod + "' in class [" + candidateAspectClass.getName() + "]"); } if (logger.isDebugEnabled()) { logger.debug("Found AspectJ method: " + candidateAdviceMethod); } AbstractAspectJAdvice springAdvice; 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); } // Now to configure the advice... springAdvice.setAspectName(aspectName); springAdvice.setDeclarationOrder(declarationOrder); String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod); if (argNames != null) { springAdvice.setArgumentNamesFromStringArray(argNames); } springAdvice.calculateArgumentBindings(); return springAdvice; }
这就是我们在之前的结构中说过的, 在解析切面的时候, 会解析切面中的每一个方法, 将其解析成一个Advisor, 而每一个Advisor都包含两个部分:Advise和pointcut.
最后, 将所有的切面类都解析完, 将所有的Advisor放入到集合advisors中返回.
这样就完成了切面的解析.
2) 调用动态代理
在ioc解析的过程中, 是在什么时候创建动态代理的呢?
通常是在创建bean初始化之后创建动态代理. 如果有循环依赖, 会在实例化之后创建动态代理, 再来感受一下创建bean过程中的操作.
下面我们来看正常的流程, 在初始化之后创建AOP动态代理 .
在创建bean的过程中,一共有三步, 来看看AbstractAutowireCpableBeanFactory.doCreateBean()
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException { // Instantiate the bean. BeanWrapper instanceWrapper = null; if (mbd.isSingleton()) { instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null) { //第一步: 实例化 instanceWrapper = createBeanInstance(beanName, mbd, args); } // 这里使用了装饰器的设计模式 final Object bean = instanceWrapper.getWrappedInstance(); Class<?> beanType = instanceWrapper.getWrappedClass(); ...... try { // 第二步:填充属性, 给属性赋值(调用set方法) 这里也是调用的后置处理器 populateBean(beanName, mbd, instanceWrapper); // 第三步: 初始化. exposedObject = initializeBean(beanName, exposedObject, mbd); } ...... }
在第三步初始化的时候, 要处理很多bean的后置处理器.
@Override public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException { Object result = existingBean; for (BeanPostProcessor processor : getBeanPostProcessors()) { Object current = processor.postProcessAfterInitialization(result, beanName); if (current == null) { return result; } result = current; } return result; }
postProcessAfterInitialization(result, beanName);就是处理初始化之后的后置处理器, 下面就从这个方法作为入口分析.
AnnotationAwareAspectJAutoProxyCreator也实现了postProcessAfterInitialization(result, beanName);接口
@Override public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) { /** * 每一个bean在解析的时候都会解析一遍切面. * 为什么每次都要解析一遍呢? 因为还有另外一种方式-实现Advisor接口的方式实现AOP, 在加载过程中, 可能随时有新的bean被解析出来. 所以, 需要每次都重新解析一遍,. * 我们在第一次解析的Advisor都已经放入到缓存, 在这里会先从缓存中取, 也就是已经解析过的不会重复解析. 也就是不 消耗性能 */ if (bean != null) { // 获取缓存key Object cacheKey = getCacheKey(bean.getClass(), beanName); /** * 因为有可能在循环依赖处理的时候已经创建国一遍, 如果是那么现在就不再创建了,并且删除 * 在这里, 我们要处理的是普通类的动态代理, 所以, 需要将循环以来创建的动态代理删掉 */ if (this.earlyProxyReferences.remove(cacheKey) != bean) { // 该方法将返回动态代理的实例 return wrapIfNecessary(bean, beanName, cacheKey); } } return bean; }
这里需要强调的一点是, 每一个bean在解析的时候都会解析一遍切面.为什么每次都要解析一遍呢?
因为创建切面有两种方式, 一种是实现Advisor接口, 另一种是注解的方式. 实现Advisor接口的方式, 在加载过程中, 可能随时有新的bean被解析出来. 所以, 需要每次都重新解析一遍.
我们在第一次解析的Advisor都已经放入到缓存, 在这里会先从缓存中取, 也就是已经解析过的不会重复解析. 也就是不 消耗性能
接下来处理的流程如下:
这里,第三步:删除循环依赖创建的动态代理对象, 为什么要这样处理呢?
因为有可能在循环依赖处理的时候已经创建了动态代理bean, 如果是,那么现在就不再创建了,并且将其删除.
在这里, 我们要处理的是普通类的动态代理, 所以, 需要将循环依赖创建的动态代理删掉
注: earlyProxyReferences对象使用来存储循环依赖过程中创建的动态代理bean. 如果循环依赖创建了这个代理bean, 那么直接返回, 如果没有创建过, 我们再创建.
下面来看看是如何创建的?
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { // 已经被处理过(解析切面的时候, targetSourcedBeans用来存储自己实现创建动态代理的逻辑) if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) { return bean; } // 判断bean是否是需要增强的bean /** * 哪些类是不需要增强的呢? * 在解析切面的时候, 基础类和应该跳过的类是不需要增强的. */ if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) { return bean; } // 判断是否是基础类, 或者是否是需要跳过的类 if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) { // 将其标记为不需要增强的类 this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; } // 匹配Advisor. 根据类匹配advisors, 至少匹配上一个, 才创建动态代理, 否则不创建动态代理 Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null); // 匹配了至少一个advisor, 创建动态代理 if (specificInterceptors != DO_NOT_PROXY) { 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; }
来看看创建流程
首先判断是否是需要跳过的类. 哪些类是需要跳过的类呢?
第一类:基础类. Advice, Pointcut, Advisor, AopInfrastructureBean.
第二类: 原始的接口类, 以.ORIGINAL开头的类
接下来, 匹配Advisor.
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) { // 第一步: 拿到已经解析出来的advisors(这次是从缓存中获取) List<Advisor> candidateAdvisors = findCandidateAdvisors(); // 第二步:循环判断advisor能否作用于当前bean(原理: 切点是否命中bean) List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName); // 第三步: 对匹配bean的advisor进行增强 extendAdvisors(eligibleAdvisors); // 第四步: 对匹配bean的advisor进行排序 if (!eligibleAdvisors.isEmpty()) { eligibleAdvisors = sortAdvisors(eligibleAdvisors); } // 返回匹配到的advisors return eligibleAdvisors; }
这里经过了四步, 具体详见上述代码及注释.
- 第一步: 从缓存中拿到已经解析出来的advisors
- 第二步:循环判断advisor能否作用于当前bean
- 第三步: 对匹配bean的advisor进行增强
- 第四步: 对匹配bean的advisor进行排序
这里面的第一步: 从缓存中取出了已经解析出来的advisors集合. 解析方式是从缓存中取出已经解析的advisors
接下来,循环遍历获得到的advisors, 得到每一个advisor. 判断advisor是否是目标bean需要增强的通知.
这里在筛选的时候, 根据切点表达式进行了两次筛选. 第一次粗筛, 第二次是精筛. 整个目标类, 只要有一个类命中切点表达式, 那么这个类就是需要被创建动态代理的类, 返回true.
接下来就是要创建动态代理了. 然后,返回创建的动态代理对象.
下面来看看是如何创建动态代理的.
创建动态代理对象有两种方式: 一种是jdk代理, 一种是cglib代理.
无论是使用xml配置的方式, 还是使用注解的方式, 都有一个参数proxy-target-class, 如果将这个参数设置为true, 表示强制使用cglib代理. 如下所示设置:
使用注解的方式
@EnableAspectJAutoProxy(proxyTargetClass=true)
使用xml配置的方式
<aop: sapectj-autoproxy proxy-target-class="true"></aop:>
所以在创建动态代理之前, 先解析注解或者配置, 看是否配置了proxy-target-class参数. 如果配置了这个参数,且其值为true, 那么就创建一个cglib代理对象. 否则创建一个JDK代理对象.通常, 我们使用的更多的是spring自己定义的JDK代理对象. 通过Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);创建动态代理
在JDKDynamicAopProxy代理类中有一个invoke()方法. 这个invoke方法, 就是执行代理对象的方法时调用的方法.
该方法是通过反射的方法执行目标类中定义的方法的.
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { }
3. 调用动态代理.
调用这里有一个非常经典的调用逻辑--调用链.
如上图, 调用链的逻辑是, 调用动态代理方法,比如说div(arg1, arg2), 然后执行调用链中第一个通知advisor1, 然后第一个通知调用第二个通知, 在执行第二个, 以此类推, 当所有的通知执行完, 调用目标方法div(arg1, arg2), 然后返回执行结果. 我们来看看代码的逻辑实现.
如下代码是调用动态代理的代码入口:
public class LxlMainClass { public static void main(String[] args) { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(MainConfig.class); Calculate calculate = (Calculate) ctx.getBean("lxlCalculate"); /** * 上面的calculate, 就是返回的动态代理的类 * 当调用下面的div方法时, 实际上调用的是JdkDynamicAopProxy.invoke(...)方法 */ calculate.div(2, 4); ProgramCalculate programCalculate = (ProgramCalculate) ctx.getBean("lxlCalculate"); String s = programCalculate.toBinary(5); System.out.println(s); } }
我们在main方法中, 获取的Calculate对象, 其实是动态代理生成的对象. 当调用calculate.div(2, 4)方法时, 其实调用的是动态代理的invoke()方法.
@Override @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; try { if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) { // The target does not implement the equals(Object) method itself. return equals(args[0]); } else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) { // The target does not implement the hashCode() method itself. return hashCode(); } else if (method.getDeclaringClass() == DecoratingProxy.class) { // There is only getDecoratedClass() declared -> dispatch to proxy config. return AopProxyUtils.ultimateTargetClass(this.advised); } // 如果方法所在类是一个接口 && 是可分配为Advised类型的方法 else if (!this.advised.opaque && method.getDeclaringClass().isInterface() && method.getDeclaringClass().isAssignableFrom(Advised.class)) { // Service invocations on ProxyConfig with the proxy config... return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args); } Object retVal; if (this.advised.exposeProxy) { // 把代理对象暴露在线程变量中. oldProxy = AopContext.setCurrentProxy(proxy); // 设置代理的上下文为true setProxyContext = true; } // Get as late as possible to minimize the time we "own" the target, // in case it comes from a pool. // 获取目标对象 target = targetSource.getTarget(); Class<?> targetClass = (target != null ? target.getClass() : null); // 把aop的advisor全部转化为拦截器, 通过责任链模式依次调用 /** * 将advisor对象转换为interceptor对象. * * 问题: 为什么要将advisor都转化为interceptor拦截器呢? * 主要还是因为要进行责任链调用. 之前说过, 要想进行责任链调用, 他们要有一个共同的方法. * 转化为interceptor以后, 这里共同的方法就是invoke(). * beforeAdivsor, afterAdvisor, returningAdvisor, throwingAdvisor. 这几种类型. 只有returningAdvisor和throwingAdvisor会转化为Interceptor. * 因为beforeAdvisor和adgerAdvisor本身就实现了interceptor接口 */ List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); // 拦截器链为空 if (chain.isEmpty()) { // 通过反射直接调用执行目标方法 Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args); retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse); } else { // 创建一个 method invocation 拦截器 MethodInvocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain); // Proceed to the joinpoint through the interceptor chain. // 通过拦截器链调用连接点 retVal = invocation.proceed(); } // Massage return value if necessary. Class<?> returnType = method.getReturnType(); if (retVal != null && retVal == target && returnType != Object.class && returnType.isInstance(proxy) && !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) { // Special case: it returned "this" and the return type of the method // is type-compatible. Note that we can't help if the target sets // a reference to itself in another returned object. retVal = proxy; } else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) { throw new AopInvocationException( "Null return value from advice does not match primitive return type for: " + method); } return retVal; } finally { if (target != null && !targetSource.isStatic()) { // Must have come from TargetSource. targetSource.releaseTarget(target); } if (setProxyContext) { // Restore old proxy. AopContext.setCurrentProxy(oldProxy); } } }
这里有两步很重要:
第一步: 将匹配的advisor转换为Interceptor
第二步: 调用责任链, 执行各类通知
先看第一步: 将匹配的advisor对象转换为interceptor拦截器对象. 为什么要将advisor转换为interceptor拦截器呢?
因为要进行责任链调用. 前面说过, 要想进行责任链调用, 他们要有一个共同的方法. 转化为interceptor以后, 共同的方法就是invoke().
@Override public List<Object> getInterceptorsAndDynamicInterceptionAdvice( Advised config, Method method, @Nullable Class<?> targetClass) { // This is somewhat tricky... We have to process introductions first, // but we need to preserve order in the ultimate list. AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance(); // 获取到匹配当前方法的所有advisor Advisor[] advisors = config.getAdvisors(); List<Object> interceptorList = new ArrayList<>(advisors.length); Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass()); Boolean hasIntroductions = null; for (Advisor advisor : advisors) { /** * 如果advisor是PointcutAdvisor类型 */ if (advisor instanceof PointcutAdvisor) { // Add it conditionally. PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor; // 注解配置信息是一个前置过滤器 或者 目标类匹配advisor的切点表达式 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) { // 将advice转换为MethodInterceptor拦截器, MethodInterceptor[] interceptors = registry.getInterceptors(advisor); if (mm.isRuntime()) { // Creating a new object instance in the getInterceptors() method // isn't a problem as we normally cache created chains. for (MethodInterceptor interceptor : interceptors) { // 将MethodInterceptor拦截器和MethodMatcher组装为一个新的对象 interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm)); } } else { // 将拦截器直接放到interceptorList中 interceptorList.addAll(Arrays.asList(interceptors)); } } } } else if (advisor instanceof IntroductionAdvisor) { // 如果advisor是IntroductionAdvisor类型 IntroductionAdvisor ia = (IntroductionAdvisor) advisor; if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) { Interceptor[] interceptors = registry.getInterceptors(advisor); interceptorList.addAll(Arrays.asList(interceptors)); } } else { // 其他类型的advisor Interceptor[] interceptors = registry.getInterceptors(advisor); interceptorList.addAll(Arrays.asList(interceptors)); } } return interceptorList; }
这里最重要的方法就是registry.getInterceptors(advisor), 在getInterceptors(advisor)里面循环遍历了advisors, 然后将每一个advisor转换为Interceptor, 这是将advisor转换为interceptor的具体实现.
我们来看看源码和逻辑
@Override public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException { List<MethodInterceptor> interceptors = new ArrayList<>(3); Advice advice = advisor.getAdvice(); if (advice instanceof MethodInterceptor) { // 如果advice已经实现了MethodInterceptor接口, 那么直接将其添加到interceptors集合中 interceptors.add((MethodInterceptor) advice); } for (AdvisorAdapter adapter : this.adapters) { // 判断是否是指定类型的advice if (adapter.supportsAdvice(advice)) { // 如果是就将其转换为对应类型的Interceptor interceptors.add(adapter.getInterceptor(advisor)); } } if (interceptors.isEmpty()) { throw new UnknownAdviceTypeException(advisor.getAdvice()); } return interceptors.toArray(new MethodInterceptor[0]); }
adapter.supportsAdvice(advice)判断advice是否是指定类型的adapter. adapter有如下几种
- MethodBeforeAdviceAdapter : 前置通知adapter
- AfterReturningAdviceAdapter:后置|放回通知adapter
- SimpleBeforeAdviceAdapter: simpler前置通知adapter
- ThrowsAdviceAdapter:异常通知adapter
这里采用的是适配器模式, 通过适配器来匹配各种不同类型的通知. 然后再调用adapter.getInterceptor(advisor)将advisor构建成Interceptor.
通常有beforeAdivsor, afterAdvisor, returningAdvisor, throwingAdvisor几种类型的通知. 只有returningAdvisor和throwingAdvisor会转化为Interceptor.
因为beforeAdvisor和afterAdvisor本身就实现了interceptor接口.
将所有的advisor转换成Interceptor以后放入到interceptors集合中返回.
接下来执行责任链调用.责任链调用的思想主要有两个
1. 递归调用
2. 所有的advisor最终都让其实现interceptor, 并重写invoke()方法.
来看一下源码
@Override @Nullable public Object proceed() throws Throwable { // We start with an index of -1 and increment early. // 如果是最后一个拦截器, 则直接执行. invokeJoinpoint()方法 if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) { return invokeJoinpoint(); } // 取出interceptorsAndDynamicMethodMatchers对象 Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex); // 如果是InterceptorAndDynamicMethodMatcher类型 if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) { // Evaluate dynamic method matcher here: static part will already have // been evaluated and found to match. InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice; Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass()); // 调用methodMather的matchs()方法 if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) { // 匹配成功, 则调用拦截器的invoke()方法 return dm.interceptor.invoke(this); } else { // Dynamic matching failed. // Skip this interceptor and invoke the next in the chain. // 动态匹配失败, 跳过此拦截器, 调用拦截器链中的下一个拦截器 return proceed(); } } else { // It's an interceptor, so we just invoke it: The pointcut will have // been evaluated statically before this object was constructed. //它是一个拦截器,因此我们只需要调用它:切入点将在构造此对象之前进行静态评估。 return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this); } }
在这里interceptorsAndDynamicMethodMatchers存放的就是所有匹配到的advisor. 按照顺序,取出advisor. 然后将其转换为MethodInterceptor以后, 调用他的invoke(this)方法,同时将传递当前对象, 在invoke(this)中在此调用proceed()方法. 循环调用. 从interceptorsAndDynamicMethodMatchers取advisor, 直到取出最后一个advisor. 再次调用proceed()则指定调用目标方法.
interceptorsAndDynamicMethodMatchers里面一共有6个advisor
具体调用如下图:
以上就是调用aop的整个过程. 内容还是很多的,需要时间消化.