文章目录
- 系列文档索引
- 六、@EnableAspectJAutoProxy源码分析
- 1、AnnotationAwareAspectJAutoProxyCreator源码
- (1)wrapIfNecessary方法
- (2)createProxy
- 2、getAdvicesAndAdvisorsForBean查找所有Advisor
- (1)findCandidateAdvisors查找
- (2)查找AspectJ定义的Advisor
- (3)getAdvisors解析切面Bean
- (4)getAdvisor:根据某个方法生成Advisor
- (5)findAdvisorsThatCanApply进行筛选(回到最初)
- (6)InstantiationModelAwarePointcutAdvisorImpl的getAdvice方法
- 3、总结
- (1)AbstractAdvisorAutoProxyCreator
- (2)@EnableAspectJAutoProxy
- (3)流程图
系列文档索引
SpringAOP从入门到源码分析大全(一)熟悉动态代理
SpringAOP从入门到源码分析大全(二)熟悉ProxyFactory
SpringAOP从入门到源码分析大全(三)ProxyFactory源码分析
SpringAOP从入门到源码分析大全(四)SpringAOP的源码分析
SpringAOP从入门到源码分析大全(五)手写一个编程式AOP
六、@EnableAspectJAutoProxy源码分析
1、AnnotationAwareAspectJAutoProxyCreator源码
使用@EnableAspectJAutoProxy,会引入一个AspectJAutoProxyRegistrar的Bean,这个Bean会注册AnnotationAwareAspectJAutoProxyCreator为BeanDefinition。
AnnotationAwareAspectJAutoProxyCreator集成了AbstractAutoProxyCreator,AbstractAutoProxyCreator实现了SmartInstantiationAwareBeanPostProcessor,在postProcessAfterInitialization方法中,会进行AOP。
注意!该方法中,如果有循环依赖的话,会对Bean提前AOP,循环依赖不是此处讨论的重点。
// org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessAfterInitialization
@Override
public 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;
}
(1)wrapIfNecessary方法
// org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#wrapIfNecessary
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {return bean;}// advisedBeans表示已经判断过了的Bean,false表示不需要再进行AOP了(循环依赖会提前AOP)if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {return bean;}// 当前正在创建的Bean不用进行AOP,比如切面Beanif (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {this.advisedBeans.put(cacheKey, Boolean.FALSE);return bean;}// Create proxy if we have advice.// 判断当前bean是否存在匹配的advice,如果存在则要生成一个代理对象// 此处根据类以及类中的方法区匹配到Interceptor(也就是Advice),然后生成代理对象,代理对象在执行的时候,还会根据当前参数进行匹配Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);if (specificInterceptors != DO_NOT_PROXY) {// advisedBeans记录了某个Bean已经进行AOP了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;
}
(2)createProxy
这就是我们熟悉的,使用ProxyFactory,进行代理对象的创建了。
// org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#createProxy
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,@Nullable Object[] specificInterceptors, TargetSource targetSource) {if (this.beanFactory instanceof ConfigurableListableBeanFactory) {AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);}ProxyFactory proxyFactory = new ProxyFactory();proxyFactory.copyFrom(this);if (proxyFactory.isProxyTargetClass()) {// Explicit handling of JDK proxy targets and lambdas (for introduction advice scenarios)if (Proxy.isProxyClass(beanClass) || ClassUtils.isLambdaClass(beanClass)) {// Must allow for introductions; can't just set interfaces to the proxy's interfaces only.for (Class<?> ifc : beanClass.getInterfaces()) {proxyFactory.addInterface(ifc);}}}else {// No proxyTargetClass flag enforced, let's apply our default checks...if (shouldProxyTargetClass(beanClass, beanName)) {proxyFactory.setProxyTargetClass(true);}else {evaluateProxyInterfaces(beanClass, proxyFactory);}}Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);proxyFactory.addAdvisors(advisors);proxyFactory.setTargetSource(targetSource);customizeProxyFactory(proxyFactory);proxyFactory.setFrozen(this.freezeProxy);if (advisorsPreFiltered()) {proxyFactory.setPreFiltered(true);}// Use original ClassLoader if bean class not locally loaded in overriding class loaderClassLoader classLoader = getProxyClassLoader();if (classLoader instanceof SmartClassLoader && classLoader != beanClass.getClassLoader()) {classLoader = ((SmartClassLoader) classLoader).getOriginalClassLoader();}return proxyFactory.getProxy(classLoader);
}
2、getAdvicesAndAdvisorsForBean查找所有Advisor
// org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#getAdvicesAndAdvisorsForBean
@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();
}// org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#findEligibleAdvisors
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {// 找到所有的AdvisorList<Advisor> candidateAdvisors = findCandidateAdvisors();// 进行筛选List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);extendAdvisors(eligibleAdvisors);// 对Advisor进行排序,按Ordered接口、@Order注解进行排序if (!eligibleAdvisors.isEmpty()) {eligibleAdvisors = sortAdvisors(eligibleAdvisors);}return eligibleAdvisors;
}
(1)findCandidateAdvisors查找
又回到了AnnotationAwareAspectJAutoProxyCreator
// org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors
@Override
protected List<Advisor> findCandidateAdvisors() {// Add all the Spring advisors found according to superclass rules.// 先找到所有Advisor类型的Bean对象,是父类的方法List<Advisor> advisors = super.findCandidateAdvisors();// Build Advisors for all AspectJ aspects in the bean factory.// 再从所有切面中解析得到Advisor对象if (this.aspectJAdvisorsBuilder != null) {advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());}return advisors;
}
(2)查找AspectJ定义的Advisor
// org.springframework.aop.aspectj.annotation.BeanFactoryAspectJAdvisorsBuilder#buildAspectJAdvisors
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<>();// 把所有的Bean拿出来遍历,判断某个bean的类型是否是AspectString[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Object.class, true, false);for (String beanName : beanNames) {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.Class<?> beanType = this.beanFactory.getType(beanName, false);if (beanType == null) {continue;}// (hasAspectAnnotation(clazz) && !compiledByAjc(clazz)); 是否有@Aspectif (this.advisorFactory.isAspect(beanType)) {aspectNames.add(beanName);// 切面的注解信息AspectMetadata amd = new AspectMetadata(beanType, beanName);// 如果@Aspect不是perthis、pertarget,那么一个切面只会生成一个对象(单例)// 并且会将该切面中所对应的Advisor对象进行缓存if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {MetadataAwareAspectInstanceFactory factory =new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);// 利用BeanFactoryAspectInstanceFactory来解析AspectList<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);if (this.beanFactory.isSingleton(beanName)) {// 缓存切面所对应的所有Advisor对象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;
}
(3)getAdvisors解析切面Bean
// org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory#getAdvisors
@Override
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.// 保证切面Bean对象只会实例化一次// 一定要注意,这里是直接new出来一个LazySingletonAspectInstanceFactoryDecorator// 也就是OrderService这个Bean在执行生命周期过程中,会需要判断要不要进行AOP,就会找到切面// 发现切面如果是pertarget或perthis,那么就会进入到这个方法,就会new LazySingletonAspectInstanceFactoryDecoratorMetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);List<Advisor> advisors = new ArrayList<>();// 获取切面类中没有加@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 = 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;
}
(4)getAdvisor:根据某个方法生成Advisor
// org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory#getAdvisor
@Override
@Nullable
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,int declarationOrderInAspect, String aspectName) {validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());// 拿到当前方法所对应的Pointcut对象,但是注意:如果当前方法上这么写@After("pointcut()")AspectJExpressionPointcut expressionPointcut = getPointcut(candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());if (expressionPointcut == null) {return null;}// expressionPointcut 是Pointcut// candidateAdviceMethod承载了advicereturn new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}
(5)findAdvisorsThatCanApply进行筛选(回到最初)
// org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#findAdvisorsThatCanApply
protected List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {ProxyCreationContext.setCurrentProxiedBeanName(beanName);try {return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);}finally {ProxyCreationContext.setCurrentProxiedBeanName(null);}
}// org.springframework.aop.support.AopUtils#findAdvisorsThatCanApply
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 processedcontinue;}// canApply就是调用Pointcut的match方法进行匹配,先根据类再根据方法if (canApply(candidate, clazz, hasIntroductions)) {eligibleAdvisors.add(candidate);}}return eligibleAdvisors;
}// org.springframework.aop.support.AopUtils#canApply(org.springframework.aop.Pointcut, java.lang.Class<?>, boolean)
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {Assert.notNull(pc, "Pointcut must not be null");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) {if (introductionAwareMethodMatcher != null ?introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :methodMatcher.matches(method, targetClass)) {return true;}}}return false;
}
(6)InstantiationModelAwarePointcutAdvisorImpl的getAdvice方法
// org.springframework.aop.aspectj.annotation.InstantiationModelAwarePointcutAdvisorImpl#getAdvice
@Override
public synchronized Advice getAdvice() {if (this.instantiatedAdvice == null) {// 根据方法生成Advicethis.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);}return this.instantiatedAdvice;
}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);
}
/// org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory#getAdvice
@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 classif (!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;
}
所以,每个注解对应了一个MethodInterceptor
@Before对应的是AspectJMethodBeforeAdvice,在进行动态代理时会把AspectJMethodBeforeAdvice转成MethodBeforeAdviceInterceptor
先执行advice对应的方法
再执行MethodInvocation的proceed(),会执行下一个Interceptor,如果没有下一个Interceptor了,会执行target对应的方法
@After对应的是AspectJAfterAdvice,直接实现了MethodInterceptor
先执行MethodInvocation的proceed(),会执行下一个Interceptor,如果没有下一个Interceptor了,会执行target对应的方法
再执行advice对应的方法
@Around对应的是AspectJAroundAdvice,直接实现了MethodInterceptor
直接执行advice对应的方法,由@Around自己决定要不要继续往后面调用
@AfterThrowing对应的是AspectJAfterThrowingAdvice,直接实现了MethodInterceptor
先执行MethodInvocation的proceed(),会执行下一个Interceptor,如果没有下一个Interceptor了,会执行target对应的方法
如果上面抛了Throwable,那么则会执行advice对应的方法
@AfterReturning对应的是AspectJAfterReturningAdvice,在进行动态代理时会把AspectJAfterReturningAdvice转成AfterReturningAdviceInterceptor
先执行MethodInvocation的proceed(),会执行下一个Interceptor,如果没有下一个Interceptor了,会执行target对应的方法
执行上面的方法后得到最终的方法的返回值
再执行Advice对应的方法
3、总结
(1)AbstractAdvisorAutoProxyCreator
DefaultAdvisorAutoProxyCreator的父类是AbstractAdvisorAutoProxyCreator。
AbstractAdvisorAutoProxyCreator非常强大以及重要,只要Spring容器中存在这个类型的Bean,就相当于开启了AOP,AbstractAdvisorAutoProxyCreator实际上就是一个BeanPostProcessor,所以在创建某个Bean时,就会进入到它对应的生命周期方法中,比如:在某个Bean初始化之后,会调用wrapIfNecessary()方法进行AOP,底层逻辑是,AbstractAdvisorAutoProxyCreator会找到所有的Advisor,然后判断当前这个Bean是否存在某个Advisor与之匹配(根据Pointcut),如果匹配就表示当前这个Bean有对应的切面逻辑,需要进行AOP,需要产生一个代理对象。
(2)@EnableAspectJAutoProxy
这个注解主要就是往Spring容器中添加了一个AnnotationAwareAspectJAutoProxyCreator类型的Bean。
AspectJAwareAdvisorAutoProxyCreator继承了AbstractAdvisorAutoProxyCreator,重写了findCandidateAdvisors()方法,AbstractAdvisorAutoProxyCreator只能找到所有Advisor类型的Bean对象,但是AspectJAwareAdvisorAutoProxyCreator除开可以找到所有Advisor类型的Bean对象,还能把@Aspect注解所标注的Bean中的@Before等注解及方法进行解析,并生成对应的Advisor对象。
所以,我们可以理解@EnableAspectJAutoProxy,其实就是像Spring容器中添加了一个AbstractAdvisorAutoProxyCreator类型的Bean,从而开启了AOP,并且还会解析@Before等注解生成Advisor。