上一章我们知道Spring开启AOP之后会注册AnnotationAwareAspectJAutoProxyCreator类的定义信息,所以在属性注入之后initializeBean的applyBeanPostProcessorsAfterInitialization方法执行的时候调用AnnotationAwareAspectJAutoProxyCreator父类(AbstractAutoProxyCreator)的postProcessAfterInitialization方法来创建AOP的代理。
// AbstractAutoProxyCreator类
@Overridepublic Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {if (bean != null) {Object cacheKey = getCacheKey(bean.getClass(), beanName);if (this.earlyProxyReferences.remove(cacheKey) != bean) {// 真正进行处理的地方,里面有代码很明显是用来创建代理对象的return wrapIfNecessary(bean, beanName, cacheKey);}}return bean;}
然后我们创建一个Aspect,方便我们这章的分析
@Component
@Aspect
public class ThamNotVeryUsefulAspect {@Pointcut("execution(* com.qhyu.cloud.aop.service.QhyuAspectService.*(..))") // the pointcut expressionprivate void thamAnyOldTransfer() {} // the pointcut signature@Before("thamAnyOldTransfer()")public void before(){System.out.println("tham Before 方法调用前");}@After("thamAnyOldTransfer()")public void after(){System.out.println("tham After 方法调用前");}@AfterReturning("thamAnyOldTransfer()")public void afterReturning(){System.out.println("tham afterReturning");}@AfterThrowing("thamAnyOldTransfer()")public void afterThrowing(){System.out.println("tham AfterThrowing");}@Around("thamAnyOldTransfer()")public Object around(ProceedingJoinPoint pjp) throws Throwable{// start stopwatchSystem.out.println("tham around before");Object retVal = pjp.proceed();// stop stopwatchSystem.out.println("tham around after");return retVal;}
}
放一张整体的流程图,方便我们查看知通构建的整体流程。
wrapIfNecessary方法的实现流程
1、首先判断bean是否需要被代理,如果不需要,直接返回原始bean实例 。
2、如果需要代理,则获取bean所有的advisor,并根据advisor的pointcout对bean进行匹配,得到所有需要拦截的方法 。
3、根据bean的类型和配置信息,决定使用哪种类型的代理对象,CGLIB或者JDK动态代理 。
4、将advisor和代理对象绑定,并将代理对象返回。
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {// targetSource是干嘛得if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {return bean;}// advisedBeans不会进行代理if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {return bean;}// 什么情况会shouldSkip,提前解析切面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;}
findCandidateAdvisors获取候选的Advisors
获取候选的Advisors是使用的子类(AnnotationAwareAspectJAutoProxuCreator)的实现,然后我们的基于注解的Aspect(ThamNotVeryUsefulAspect)会执行this.aspectJAdvisorsBuilder.buildAspectJAdvisors()来添加
@Overrideprotected List<Advisor> findCandidateAdvisors() {// Add all the Spring advisors found according to superclass rules.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;}
构建AspectJ的Advisors
首先在BeanFactoryAspectJAdvisorsBuilder的this.advisorFactory.getAdvisors(factory)打个断点
然后我断点进来之后我就发现了这个其实是有顺序的,也就是说明在这个内部实现了第一次排序。
第一次排序
接下来会进入ReflectiveAspectJAdvisorFactory的getAdvisors方法。其中核心就是for循环中的getAdvisorMethods方法。
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();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<>();//遍历切面方法,这里会把标注了@Pointcut 注解的排除掉,只剩下通知注解,如@Before,@Afterfor (Method method : getAdvisorMethods(aspectClass)) {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;}// 遍历切面方法时进行排序,可以理解为第一次排序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;}
首先会排除@PointCut的方法
private static final MethodFilter adviceMethodFilter = ReflectionUtils.USER_DECLARED_METHODS.and(method -> (AnnotationUtils.getAnnotation(method, Pointcut.class) == null));
然后创建了一个比较器
private static final Comparator<Method> adviceMethodComparator;static {// Note: although @After is ordered before @AfterReturning and @AfterThrowing,// an @After advice method will actually be invoked after @AfterReturning and// @AfterThrowing methods due to the fact that AspectJAfterAdvice.invoke(MethodInvocation)// invokes proceed() in a `try` block and only invokes the @After advice method// in a corresponding `finally` block.Comparator<Method> adviceKindComparator = new ConvertingComparator<>(new InstanceComparator<>(Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class),(Converter<Method, Annotation>) method -> {AspectJAnnotation<?> ann = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(method);return (ann != null ? ann.getAnnotation() : null);});Comparator<Method> methodNameComparator = new ConvertingComparator<>(Method::getName);adviceMethodComparator = adviceKindComparator.thenComparing(methodNameComparator);}
很明显是按照Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class的顺序进行顺序的构建。
第二次排序
根据AbstractAdvisorAutoProxyCreator的findEligibleAdvisors的代码可知,第一次排序发生在findCandidateAdvisors方法。第二次排序则发生在次方法中的sortAdvisors。
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {List<Advisor> candidateAdvisors = findCandidateAdvisors();// Around before after afterReturing afterThrowingList<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);extendAdvisors(eligibleAdvisors);if (!eligibleAdvisors.isEmpty()) {// 这里是通过order进行排序的eligibleAdvisors = sortAdvisors(eligibleAdvisors);}return eligibleAdvisors;}
第一次排序是对一个Aspect中的所有advice进行排序,第二次排序是对Aspect进行排序,可以通过实现Order接口或者@Order注解来设置顺序,如果没有实现order的话,是以加载的顺序来的。一般情况下加载的顺序可能不可控,所以如果有必要的话需要实现order。
创建两个Aspect,然后都没有实现@Order
顺序是ThamNotVersyUsefulAspect在NotVeryUsefulAspect之前
但是如果我们把两个放一起,这个时候NotVeryUsefulAspect先加载就会在前面。
如果我们设置ThamNotVeryUsefulAspect的Order(98),NotVeryUsefulAspect的Order(99),Order小的将排在前面。
@Component
@Aspect
@Order(99)
public class NotVeryUsefulAspect {
}@Component
@Aspect
@Order(98)
public class ThamNotVeryUsefulAspect {
}
写在最后
本章主要描述构建通知的顺序,正在的执行过程将在下一章节进行分析。