在上一篇博文中我们说到了通过自定义配置完成了对AnnotationAwareAspectJAutoProxyCreator
类型的自动注册,那么这个类究竟做了什么工作从而完成AOP的操作呢?首先我们看一下AnnotationAwareAspectJAutoProxyCreator
的类图结构,如图:
从UML类图中我们看到`AnnotationAwareAspectJAutoProxyCreator`这个类实现了`BeanPostProcessor`接口,而实现这个`BeanPostProcessor`后,当Spring加载这个Bean时会在实例化之前调用器`postProcessorAfterIntialization`方法,而我们就从这里进行分析AOP的逻辑
首先我们先看一下它父类AbstractAutoProxyCreator
的postProcessorIntialization
方法
看源码(具体实现在AbstractAutoProxyCreator.class
)
/** * Create a proxy with the configured interceptors if the bean is * identified as one to proxy by the subclass. * @see #getAdvicesAndAdvisorsForBean */ @Override public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) { if (bean != null) { // 根据bean的class 和 name构建出一个key 格式:beanClassName_beanName Object cacheKey = getCacheKey(bean.getClass(), beanName); if (this.earlyProxyReferences.remove(cacheKey) != bean) { // 如果它适合被代理,则需要指定封装bean return wrapIfNecessary(bean, beanName, cacheKey); } } return bean; }
在上面代码中用到了方法wrapIfNecessary
,进入到该函数方法的内部:
AbstractAutoProxyCreator.class
)protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { // 如果已经处理过 if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) { return bean; } // 无需增强 if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) { return bean; } // 给定的bean类是否是一个基础设施类,基础设施类不应该被代理,或者配置了指定的bean不需要代理 if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) { this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; } // 如果存在增强方法则创建 // Create proxy if we have advice. Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null); 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; }
从上面的函数中我们可以大概看出代理的创建过程的一个雏形。当然真正的开始之前还需要一些个判断,比如是否已经处理过或者是 是否需要跳过的bean,而真正创建代理的代码是在`getAdvicesAndAdvisorsForBean`函数开始的。
** 创建代理需要两个步骤:**
上述两个步骤其中逻辑是十分复杂的,首先来看看获取增强方法的逻辑实现。获取增强的方法getAdvicesAndAdvisorsForBean
是在AbstractAdvisorAuroProxyCreator
中实现的,代码如下:
AbstractAdvisorAuroProxyCreator.class
)@Override @Nullable protected Object[] getAdvicesAndAdvisorsForBean( Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) { List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName); if (advisors.isEmpty()) { return DO_NOT_PROXY; } return advisors.toArray(); }
主要查看上述函数体内的findEligibleAdvisor
方法。进入该方法实现也在AbstractAdvisorAuroProxyCreator.class
中
AbstractAdvisorAutoProxyCreator.class
)protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) { List<Advisor> candidateAdvisors = findCandidateAdvisors(); List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName); extendAdvisors(eligibleAdvisors); if (!eligibleAdvisors.isEmpty()) { eligibleAdvisors = sortAdvisors(eligibleAdvisors); } return eligibleAdvisors; }
通过findEligbleAdvisor
的具体实现我们看到,对于指定bean的增强方法的获取包含了两个步骤:
函数中的findCandidateAdvisors
和findAdvisorsThatCanApply
便是做了这两件事
当然如果这个方法没有找到增强器,getAdvicesAndAdvisorsForBean
就会返回一个DO_NOT_PROXY
,DO_NOT_PROXY时已经定义好的null
从一开始我们分析的就是基于注解进行的AOP,所以对于findidateAdvisors
的实现是由AnnotationAwareAspectJAutoProxyCreator
类的findCandidateAdvisors
方法完成的。
AnnotationAwareAspectJAutoProxyCreator.class
)@Override protected List<Advisor> findCandidateAdvisors() { // Add all the Spring advisors found according to superclass rules. // 当使用注解方式配置AOP的时候并不是对xml配置文件的支持进行了丢弃 // 在这里调用父类加载配置文件中的AOP声明 List<Advisor> advisors = super.findCandidateAdvisors(); // Build Advisors for all AspectJ aspects in the bean factory. if (this.aspectJAdvisorsBuilder != null) { advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors()); } return advisors; }
首先我们先看一下AnnotationAwareAspectJAutoProxyCreator.class
这个类的UML,
在上图中我们看到AnnotationAwareAspectJAutoProxyCreator间接继承了AbstractAdvisorsAutoProxyCreator,在实现获取增强方法中保留了父类的获取配置文件中定义的增强,是由List<Advisor> advisors = super.findCandidateAdvisors();
实现;
此外同时还添加了获取Bean的注解增强的功能,是由this.aspectJAdvisorsBuilder.buildAspectJAdvisors()
这个方法实现的
Spring获取增强器(增强方法)的解析思路大致如下:
接下来我们分析一下以上步骤的实现,首先
BeanFactoryAspectJAdvisorsBuilder.class
)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<>(); // 获取所有的beanName String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors( this.beanFactory, Object.class, true, false); // 循环所有的beanName获取 获取声明AspectJ的类,找出对应的增强方法 for (String beanName : beanNames) { // 不合法的bean 则略过,由子类定义规则返回true if (!isEligibleBean(beanName)) { continue; } // We must be careful not to instantiate beans eagerly as in this case they // would be cached by the Spring container but would not have been weaved. // 获取对应的bean Class类型 Class<?> beanType = this.beanFactory.getType(beanName, false); if (beanType == null) { continue; } if (this.advisorFactory.isAspect(beanType)) { aspectNames.add(beanName); AspectMetadata amd = new AspectMetadata(beanType, beanName); if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) { MetadataAwareAspectInstanceFactory factory = new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName); // 解析标记AspectJ注解的增强方法 List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory); if (this.beanFactory.isSingleton(beanName)) { // 将增强器加入缓存 下次可以直接取 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); advisors.addAll(this.advisorFactory.getAdvisors(factory)); } } } this.aspectBeanNames = aspectNames; return advisors; } } } if (aspectNames.isEmpty()) { return Collections.emptyList(); } // 记录在缓存中 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; }
执行到此,Spring就完成了Advisor的提取,在上面的步骤中**最繁杂最重要**的就是增强**器的获取**,而这一步又交给了`getAdvisors`方法去实现的。(`this.advisorFactory.getAdvisors(factory);`)
AbstractAspectJAdvisorFactory.class
)@Override public boolean isAspect(Class<?> clazz) { return (hasAspectAnnotation(clazz) && !compiledByAjc(clazz)); } private boolean hasAspectAnnotation(Class<?> clazz) { return (AnnotationUtils.findAnnotation(clazz, Aspect.class) != null); }
紧接着再查看一下findAnnotation
方法:
@Nullable public static <A extends Annotation> A findAnnotation(Class<?> clazz, @Nullable Class<A> annotationType) { if (annotationType == null) { return null; } // Shortcut: directly present on the element, with no merging needed? if (AnnotationFilter.PLAIN.matches(annotationType) || AnnotationsScanner.hasPlainJavaAnnotationsOnly(clazz)) { // 判断此Class 是否存在Aspect.class注解 A annotation = clazz.getDeclaredAnnotation(annotationType); if (annotation != null) { return annotation; } // For backwards compatibility, perform a superclass search with plain annotations // even if not marked as @Inherited: e.g. a findAnnotation search for @Deprecated Class<?> superclass = clazz.getSuperclass(); if (superclass == null || superclass == Object.class) { return null; } return findAnnotation(superclass, annotationType); } // Exhaustive retrieval of merged annotations... return MergedAnnotations.from(clazz, SearchStrategy.TYPE_HIERARCHY, RepeatableContainers.none()) .get(annotationType).withNonMergedAttributes() .synthesize(MergedAnnotation::isPresent).orElse(null); }
这里如果bean存在Aspect.class注解,那么就可以获取此bean的增强器了,接下来我们回到BeanFactoryAspectJAdvisorsBuilder类中查看this.advisorFactory.getAdvisors(factory);方法。
ReflectiveAspectJAdvisorFactory.class
)@Override public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) { // 获取标记AspectJ的类 Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass(); // 获取标记AspectJ的name String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName(); validate(aspectClass); // We need to wrap the MetadataAwareAspectInstanceFactory with a decorator // so that it will only instantiate once. MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory = new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory); List<Advisor> advisors = new ArrayList<>(); // 对于aspect class的每一个带有注解的方法进行循环(除了@Pointcut注解的方法除外),取得Advisor,并添加到集合里 // 这里应该取到的是Advice,然后取得我们自定义的切面类中的PointCut,组合成Advisor for (Method method : getAdvisorMethods(aspectClass)) { // Prior to Spring Framework 5.2.7, advisors.size() was supplied as the declarationOrderInAspect // to getAdvisor(...) to represent the "current position" in the declared methods list. // However, since Java 7 the "current position" is not valid since the JDK no longer // returns declared methods in the order in which they are declared in the source code. // Thus, we now hard code the declarationOrderInAspect to 0 for all advice methods // discovered via reflection in order to support reliable advice ordering across JVM launches. // Specifically, a value of 0 aligns with the default value used in // AspectJPrecedenceComparator.getAspectDeclarationOrder(Advisor). // 将类中的方法封装成Advisor Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, 0, aspectName); if (advisor != null) { advisors.add(advisor); } } // If it's a per target aspect, emit the dummy instantiating aspect. if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) { Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory); advisors.add(0, instantiationAdvisor); } // Find introduction fields. for (Field field : aspectClass.getDeclaredFields()) { Advisor advisor = getDeclareParentsAdvisor(field); if (advisor != null) { advisors.add(advisor); } } return advisors; }
普通增强其的获取逻辑通过getAdvisor
方法实现,实现步骤包括对切点的注解的获取以及根据注解信息生成增强。
首先我们看一下 getAdvisorMethods(aspectClass)这个方法,它很巧妙的使用接口定义一个匿名回调,把带有注解的Method都取出来,放到集合里。
private List<Method> getAdvisorMethods(Class<?> aspectClass) { List<Method> methods = new ArrayList<>(); ReflectionUtils.doWithMethods(aspectClass, methods::add, adviceMethodFilter); if (methods.size() > 1) { methods.sort(adviceMethodComparator); } return methods; }
然后在看一下函数体内的doWithMethods
方法 具体实现在ReflectionUtils中
public static void doWithMethods(Class<?> clazz, MethodCallback mc, @Nullable MethodFilter mf) { // Keep backing up the inheritance hierarchy. Method[] methods = getDeclaredMethods(clazz, false); for (Method method : methods) { if (mf != null && !mf.matches(method)) { continue; } try { mc.doWith(method); } catch (IllegalAccessException ex) { throw new IllegalStateException("Not allowed to access method '" + method.getName() + "': " + ex); } } if (clazz.getSuperclass() != null && (mf != USER_DECLARED_METHODS || clazz.getSuperclass() != Object.class)) { doWithMethods(clazz.getSuperclass(), mc, mf); } else if (clazz.isInterface()) { for (Class<?> superIfc : clazz.getInterfaces()) { doWithMethods(superIfc, mc, mf); } } }
然后我们在回到ReflectiveAspectJAdvisorFactory.class类中获取普通增强器的getAdvisor方法
ReflectiveAspectJAdvisorFactory.class
)@Override @Nullable public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrderInAspect, String aspectName) { validate(aspectInstanceFactory.getAspectMetadata().getAspectClass()); // 获取Pointcut信息 主要是获取Pointcut表达式 // 把Method对象也传进去的目的是,比较Method对象上的注解,是不是下面的注解的其中的一个, // 如果不是返回null;如果是就把Pointcut内容包装返回 AspectJExpressionPointcut expressionPointcut = getPointcut( candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass()); if (expressionPointcut == null) { return null; } // 根据Pointcut信息生成增强器 return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod, this, aspectInstanceFactory, declarationOrderInAspect, aspectName); }
所谓获取切点信息就是指注解的表达式信息的获取,如@Before("test()")。
ReflectiveAspectJAdvisorFactory.class
)@Nullable private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) { // 获取方法上的注解,比较Method对象上的注解是不是下面其中的一个,如果不是返回null // 被比较的注解:Pointcut.class, Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class AspectJAnnotation<?> aspectJAnnotation = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod); if (aspectJAnnotation == null) { return null; } // 使用AspectJExpressionPointcut实例封装获取的信息 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; }
我们再看一下上面使用到的findAspectJAnnotationOnMethod
方法的实现
AbstractAspectJAdvisorFactory.class
)@Nullable protected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) { for (Class<?> clazz : ASPECTJ_ANNOTATION_CLASSES) { AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) clazz); if (foundAnnotation != null) { return foundAnnotation; } } return null; }
小插曲:注意一下上面的ASPECTJ_ANNOTATION_CLASSES
变量,它设置了查找的注解类:
private static final Class<?>[] ASPECTJ_ANNOTATION_CLASSES = new Class<?>[] { Pointcut.class, Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class};
再次回到findAspectJAnnotationOnMethod方法的实现,里面使用了findAnnotation
方法,跟踪该方法
AbstractAspectAdvisorFacrory.class
)/** * 获取指定方法上的注解 并使用AspectAnnotation进行封装 * @param method * @param toLookFor * @param <A> * @return */ @Nullable private static <A extends Annotation> AspectJAnnotation<A> findAnnotation(Method method, Class<A> toLookFor) { A result = AnnotationUtils.findAnnotation(method, toLookFor); if (result != null) { return new AspectJAnnotation<>(result); } else { return null; } }
此方法的功能是获取指定方法上的注解并使用AspectJAnnotation封装。
所有的增强都由Advisor实现类InstantiationModelAwarePointCutAdvisorImpl进行统一封装。我们简单看一下其构造函数:
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; this.aspectJAdvisorFactory = aspectJAdvisorFactory; this.aspectInstanceFactory = aspectInstanceFactory; 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); // Make it dynamic: must mutate from pre-instantiation to post-instantiation state. // If it's not a dynamic pointcut, it may be optimized out // by the Spring AOP infrastructure after the first evaluation. this.pointcut = new PerTargetInstantiationModelPointcut( this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory); this.lazy = true; } else { // A singleton aspect. this.pointcut = this.declaredPointcut; this.lazy = false; // 初始化Advice this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut); } }
通过对上面的构造函数的分析,发现封装过程只是简单的将信息封装在类的实例中,所有的信息都是单纯的复制。在实例初始化的工程中还完成了对于增强器的初始化。因为不同的增强所体现的逻辑是不同的,比如`@Before("test()")`和`@After("test()")`标签的不同就是增强器的位置不同,所以需要不同的增强器来完成不同的逻辑,而根据注解中的信息初始化对应的增强器就是在`instantiateAdvice`函数中实现的,继续跟踪源码:
private Advice instantiateAdvice(AspectJExpressionPointcut pointcut) { Advice advice = this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pointcut, this.aspectInstanceFactory, this.declarationOrder, this.aspectName); return (advice != null ? advice : EMPTY_ADVICE); }
接下来再继续跟踪getAdvice函数的具体实现
ReflectiveAspectJAdvisorFactory.class
)@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; }
从上面的函数中我们看到,Spring会根据不同的注解生成不同的增强器,具体表现在了switch (aspectJAnnotation.getAnnotationType())
,根据不同的类型来生成。例如在AtBefore会对应AspectJMethodBeforeAdvice,早AspectJMethodBeforeAdvice中完成了增强逻辑,
并且这里的**AspectJMethodBeforeAdvice**最后被适配器封装成**MethodBeforeAdviceInterceptor**,
如何被封装的 这有机再在分析。
我们先看一下MethodBeforeAdviceInterceptor的代码
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice, Serializable { private final MethodBeforeAdvice advice; /** * Create a new MethodBeforeAdviceInterceptor for the given advice. * @param advice the MethodBeforeAdvice to wrap */ public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) { Assert.notNull(advice, "Advice must not be null"); this.advice = advice; } @Override @Nullable public Object invoke(MethodInvocation mi) throws Throwable { this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis()); return mi.proceed(); } }
其中上述代码的MethodBeforeAdvice
代表的前置增强的AspectJMethodBeforeAdvice
,根据before
方法来到这个类。
AspectJMethodBeforeAdvice.java
)@Override public void before(Method method, Object[] args, @Nullable Object target) throws Throwable { // 直接调用增强方法 invokeAdviceMethod(getJoinPointMatch(), null, null); }
继续跟踪函数体内的invokeAdviceMethod
方法
AbstractAspectJAdvice.java
)protected Object invokeAdviceMethod( @Nullable JoinPointMatch jpMatch, @Nullable Object returnValue, @Nullable Throwable ex) throws Throwable { return invokeAdviceMethodWithGivenArgs(argBinding(getJoinPoint(), jpMatch, returnValue, ex)); }
接着继续根据函数体内的invokeAdviceMethodWithGivenArgs
方法,
AbstractAspectJAdvice.java
)protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable { Object[] actualArgs = args; if (this.aspectJAdviceMethod.getParameterCount() == 0) { actualArgs = null; } try { ReflectionUtils.makeAccessible(this.aspectJAdviceMethod); // 通过反射调用AspectJ注解类中的增强方法 return this.aspectJAdviceMethod.invoke(this.aspectInstanceFactory.getAspectInstance(), actualArgs); } catch (IllegalArgumentException ex) { throw new AopInvocationException("Mismatch on arguments to advice method [" + this.aspectJAdviceMethod + "]; pointcut expression [" + this.pointcut.getPointcutExpression() + "]", ex); } catch (InvocationTargetException ex) { throw ex.getTargetException(); } }
invokeAdviceMethodWithGivenArgs方法中的aspectJAdviceMethod正是对前置增强的方法,在这里实现了调用。
简单总结:
前置通知的大致过程是在拦截器链中放置MethodBeforeAdviceInterceptor,而在MethodBeforeAdvivceInterceptor中又放置了AspectJMethodBeforeAdvice,并在调用invoke时首先串联调用。
相比前置增强略有不同,后置增强没有提供中间的类,而是直接在拦截器中使用过了中间的
AspectJAfterAdvice
,也就是直接实现了MethodInterceptor
。
public class AspectJAfterAdvice extends AbstractAspectJAdvice implements MethodInterceptor, AfterAdvice, Serializable { public AspectJAfterAdvice( Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) { super(aspectJBeforeAdviceMethod, pointcut, aif); } @Override @Nullable public Object invoke(MethodInvocation mi) throws Throwable { try { return mi.proceed(); } finally { // 激活增强方法 invokeAdviceMethod(getJoinPointMatch(), null, null); } } @Override public boolean isBeforeAdvice() { return false; } @Override public boolean isAfterAdvice() { return true; } }
其他的几个增强器,下次具体来看
前面的函数中已经完成了所有增强器的解析,也就是讲解完了关于`findCandidateAdvisors`方法;但是对于所有增强器来讲,并不一定都适用于当前的bean,还要取出适合的增强器,也就是满足我们配置的通配符的增强器,具体实现在`findAdvisorsThatCanAply`中,我们需要回到最初的**AbstractAdvisorAuroProxyCreator**类中,然后进入到findEligibleAdvisors函数内的**findAdvisorsThatCanAply**方法的实现:
AbstractAdvisorAuroProxyCreator.java
)protected List<Advisor> findAdvisorsThatCanApply( List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) { ProxyCreationContext.setCurrentProxiedBeanName(beanName); try { // 过滤已经得到的advisors return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass); } finally { ProxyCreationContext.setCurrentProxiedBeanName(null); } }
继续跟踪findAdvisorsThatCanApply
方法:
AOPUtils.java
)public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) { if (candidateAdvisors.isEmpty()) { return candidateAdvisors; } List<Advisor> eligibleAdvisors = new ArrayList<>(); // 首先处理引介增强 /* * 引介增强是一种特殊的增强,其它的增强是方法级别的增强,即只能在方法前或方法后添加增强。 * 而引介增强则不是添加到方法上的增强, 而是添加到类方法级别的增强,即可以为目标类动态实现某个接口, * 或者动态添加某些方法。我们通过下面的事例演示引介增强的使用 */ for (Advisor candidate : candidateAdvisors) { if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) { eligibleAdvisors.add(candidate); } } boolean hasIntroductions = !eligibleAdvisors.isEmpty(); for (Advisor candidate : candidateAdvisors) { if (candidate instanceof IntroductionAdvisor) { // already processed continue; } // 对于普通bean的 进行处理 if (canApply(candidate, clazz, hasIntroductions)) { eligibleAdvisors.add(candidate); } } return eligibleAdvisors; }
findAdvisorsThatCanApply函数的主要功能时寻找增强器中适用于当前class的增强器。引介增强与普通增强的处理是不一样的,所以分开处理。而对于真正的匹配在canApply
中实现。
接着跟踪canApply
方法
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) { Assert.notNull(pc, "Pointcut must not be null"); // 通过Pointcut的条件判断此类是否匹配 if (!pc.getClassFilter().matches(targetClass)) { return false; } MethodMatcher methodMatcher = pc.getMethodMatcher(); if (methodMatcher == MethodMatcher.TRUE) { // No need to iterate the methods if we're matching any method anyway... return true; } IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null; if (methodMatcher instanceof IntroductionAwareMethodMatcher) { introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher; } Set<Class<?>> classes = new LinkedHashSet<>(); if (!Proxy.isProxyClass(targetClass)) { classes.add(ClassUtils.getUserClass(targetClass)); } classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass)); for (Class<?> clazz : classes) { // 反射获取类中所有的方法 Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz); for (Method method : methods) { // 根据匹配原则判断该方法是否能匹配Pointcut中的规则,如果有一个方法匹配则返回true if (introductionAwareMethodMatcher != null ? introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) : methodMatcher.matches(method, targetClass)) { return true; } } } return false; }
首先会判断bean是否满足切点的规则,如果能满足,则获取bean的所有方法,判断是否有方法能够匹配规则,有方法匹配规则就代表Advisor能作用于该bean,该方法就会返回true,然后findAdvisorsThatCanApply
函数就会将Advisor加入到eligibleAdvisors中。
AnnotationMethodMatcher.java
)@Override public boolean matches(Method method, Class<?> targetClass) { if (matchesMethod(method)) { return true; } // Proxy classes never have annotations on their redeclared methods. if (Proxy.isProxyClass(targetClass)) { return false; } // The method may be on an interface, so let's check on the target class as well. Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass); return (specificMethod != method && matchesMethod(specificMethod)); } private boolean matchesMethod(Method method) { // 可以看出判断该Advisor是否使用于bean中的method,只需看method上是否有Advisor的注解 return (this.checkInherited ? AnnotatedElementUtils.hasAnnotation(method, this.annotationType) : method.isAnnotationPresent(this.annotationType)); }
至此:在后置处理器中找到了所有匹配Bean中的增强器,