1. SpringBoot 中代理对象的创建者
Spring 是基于动态代理实现的 aop,其核心在于代理类增强目标类的功能。这样对于每一个目标类,如何创建其代理对象就极为关键。从源码来看,Spring 中代理对象的创建都离不开AnnotationAwareAspectJAutoProxyCreator
,这个类实现了BeanPostProcessor
接口,会在每个bean实例创建时检查该bean是否需要创建代理,需要的话就创建相应的代理
基于 SpringBoot 的自动配置机制,在注解
@EnableAspectJAutoProxy
的定义中会通过@Import(AspectJAutoProxyRegistrar.class)
将注册类引入,而在AspectJAutoProxyRegistrar
的注册 bean 定义方法中会通过代码AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary()
最终将AnnotationAwareAspectJAutoProxyCreator
注册到 bean 工厂中
AnnotationAwareAspectJAutoProxyCreator
的继承结构如下:
2. 代理对象创建流程
2.1 代理对象创建者的注册
SpringBoot 启动过程中会将各个自动配置类加载进容器,其中就包括了 Aop 的自动配置类
AopAutoConfiguration
。在该类会根据配置属性spring.aop.auto
来决定是否启用自动代理,一般默认为启用。另外也会启动注解@EnableAspectJAutoProxy
来决定代理的实现方式@Configuration@ConditionalOnClass({ EnableAspectJAutoProxy.class, Aspect.class, Advice.class, AnnotatedElement.class})@ConditionalOnProperty(prefix="spring.aop", name="auto", havingValue="true", matchIfMissing=true)publicclassAopAutoConfiguration{@Configuration@EnableAspectJAutoProxy(proxyTargetClass=false)@ConditionalOnProperty(prefix="spring.aop", name="proxy-target-class", havingValue="false", matchIfMissing=false)publicstaticclassJdkDynamicAutoProxyConfiguration{}@Configuration@EnableAspectJAutoProxy(proxyTargetClass=true)@ConditionalOnProperty(prefix="spring.aop", name="proxy-target-class", havingValue="true", matchIfMissing=true)publicstaticclassCglibAutoProxyConfiguration{}}
@EnableAspectJAutoProxy
通过@Import(AspectJAutoProxyRegistrar.class)
引入了注册类AspectJAutoProxyRegistrar
@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Import(AspectJAutoProxyRegistrar.class)public @interfaceEnableAspectJAutoProxy{booleanproxyTargetClass()defaultfalse;booleanexposeProxy()defaultfalse;}
AspectJAutoProxyRegistrar
实现了接口ImportBeanDefinitionRegistrar
, 在框架启动过程中会回调其实现的接口方法registerBeanDefinitions()
,将相关 bean 注册到容器中,这个过程实际是由AopConfigUtils
实现@OverridepublicvoidregisterBeanDefinitions( AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry){ AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry); AnnotationAttributes enableAspectJAutoProxy= AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);if(enableAspectJAutoProxy!= null){if(enableAspectJAutoProxy.getBoolean("proxyTargetClass")){ AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);}if(enableAspectJAutoProxy.getBoolean("exposeProxy")){ AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);}}}
AopConfigUtils#registerAspectJAnnotationAutoProxyCreatorIfNecessary()
最终调用到其内部方法registerAspectJAnnotationAutoProxyCreatorIfNecessary()
,将AnnotationAwareAspectJAutoProxyCreator
bean 定义注册到了 bean 工厂中@Nullablepublicstatic BeanDefinitionregisterAspectJAnnotationAutoProxyCreatorIfNecessary( BeanDefinitionRegistry registry,@Nullable Object source){returnregisterOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);}
2.2 代理对象创建的入口
容器启动的过程中,会在环境准备完成的时候进行 bean 的创建工作。这部分可参考Spring 启动流程源码解析,在刷新容器的时候
AbstractApplicationContext#refresh()
方法被调用,该方法会调用到AbstractApplicationContext#registerBeanPostProcessors()
将所有实现了BeanPostProcessor
接口的类从 bean 工厂注册到容器中。bean 对象的创建最终在方法finishBeanFactoryInitialization()
完成protectedvoidfinishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory){// Initialize conversion service for this context.if(beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME)&& beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)){ beanFactory.setConversionService( beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));}......
beanFactory.getBean()
的实现在AbstractBeanFactory
中,会调用到AbstractBeanFactory#doGetBean()
方法,进一步调用getObjectForBeanInstance()
方法对 bean 对象做处理protected<T> TdoGetBean(final String name,@Nullablefinal Class<T> requiredType,@Nullablefinal Object[] args,boolean typeCheckOnly)throws BeansException{final String beanName=transformedBeanName(name); Object bean;// Eagerly check singleton cache for manually registered singletons. Object sharedInstance=getSingleton(beanName);if(sharedInstance!= null&& args== null){...... bean=getObjectForBeanInstance(sharedInstance, name, beanName, null);}......}
getObjectForBeanInstance()
会判断当前 bean 实例的相关属性,从而决定是否通过方法getObjectFromFactoryBean()
去获取工厂 beanprotected ObjectgetObjectForBeanInstance( Object beanInstance, String name, String beanName,@Nullable RootBeanDefinition mbd){// Don't let calling code try to dereference the factory if the bean isn't a factory.if(BeanFactoryUtils.isFactoryDereference(name)){if(beanInstanceinstanceofNullBean){return beanInstance;}if(!(beanInstanceinstanceofFactoryBean)){thrownewBeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());}}// Now we have the bean instance, which may be a normal bean or a FactoryBean.// If it's a FactoryBean, we use it to create a bean instance, unless the// caller actually wants a reference to the factory.if(!(beanInstanceinstanceofFactoryBean)|| BeanFactoryUtils.isFactoryDereference(name)){return beanInstance;} Object object= null;if(mbd== null){ object=getCachedObjectForFactoryBean(beanName);}if(object== null){// Return bean instance from factory. FactoryBean<?> factory=(FactoryBean<?>) beanInstance;// Caches object obtained from FactoryBean if it is a singleton.if(mbd== null&&containsBeanDefinition(beanName)){ mbd=getMergedLocalBeanDefinition(beanName);}boolean synthetic=(mbd!= null&& mbd.isSynthetic()); object=getObjectFromFactoryBean(factory, beanName,!synthetic);}return object;}
getObjectFromFactoryBean()
的实现在FactoryBeanRegistrySupport
中,根据 boolean 参数shouldPostProcess
来决定是否对 bean 实例调用postProcessObjectFromFactoryBean()
方法进行处理protected ObjectgetObjectFromFactoryBean(FactoryBean<?> factory, String beanName,boolean shouldPostProcess){if(factory.isSingleton()&&containsSingleton(beanName)){synchronized(getSingletonMutex()){ Object object=this.factoryBeanObjectCache.get(beanName);if(object== null){ object=doGetObjectFromFactoryBean(factory, beanName);// Only post-process and store if not put there already during getObject() call above// (e.g. because of circular reference processing triggered by custom getBean calls) Object alreadyThere=this.factoryBeanObjectCache.get(beanName);if(alreadyThere!= null){ object= alreadyThere;}else{if(shouldPostProcess){if(isSingletonCurrentlyInCreation(beanName)){// Temporarily return non-post-processed object, not storing it yet..return object;}beforeSingletonCreation(beanName);try{ object=postProcessObjectFromFactoryBean(object, beanName);}catch(Throwable ex){thrownewBeanCreationException(beanName,"Post-processing of FactoryBean's singleton object failed", ex);}finally{afterSingletonCreation(beanName);}}if(containsSingleton(beanName)){this.factoryBeanObjectCache.put(beanName, object);}}}return object;}}else{ Object object=doGetObjectFromFactoryBean(factory, beanName);if(shouldPostProcess){try{ object=postProcessObjectFromFactoryBean(object, beanName);}catch(Throwable ex){thrownewBeanCreationException(beanName,"Post-processing of FactoryBean's object failed", ex);}}return object;}}
postProcessObjectFromFactoryBean()
方的实现在AbstractAutowireCapableBeanFactory
中,在该方法内会调用其内部方法applyBeanPostProcessorsAfterInitialization()
遍历调用BeanPostProcessor
实现类的postProcessAfterInitialization()
方法@Overridepublic ObjectapplyBeanPostProcessorsAfterInitialization(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;}
上文已经提及
AnnotationAwareAspectJAutoProxyCreator
的继承结构,以上步骤最终会调用到AnnotationAwareAspectJAutoProxyCreator
的超类AbstractAutoProxyCreator
的postProcessAfterInitialization()
方法,在该方法内调用的wrapIfNecessary()
方法就是创建代理对象的核心入口public ObjectpostProcessAfterInitialization(@Nullable Object bean, String beanName){if(bean!= null){ Object cacheKey=getCacheKey(bean.getClass(), beanName);if(!this.earlyProxyReferences.contains(cacheKey)){returnwrapIfNecessary(bean, beanName, cacheKey);}}return bean;}
2.3 切面的解析与适配
AbstractAutoProxyCreator#wrapIfNecessary()
方法中首先会调用getAdvicesAndAdvisorsForBean()
方法尝试去获取能够应用到给定 bean 上的切面,这个方法由其子类AbstractAdvisorAutoProxyCreator
实现;之后通过createProxy()
方法将切面应用到 bean 上去创建代理对象protected ObjectwrapIfNecessary(Object bean, String beanName, Object cacheKey){......// Create proxy if we have advice.// 1. 尝试获取能够应用到 bean 上的切面 Object[] specificInterceptors=getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);if(specificInterceptors!= DO_NOT_PROXY){this.advisedBeans.put(cacheKey, Boolean.TRUE);// 2. 将切面应用到 bean 上创建代理对象 Object proxy=createProxy( bean.getClass(), beanName, specificInterceptors,newSingletonTargetSource(bean));this.proxyTypes.put(cacheKey, proxy.getClass());return proxy;}this.advisedBeans.put(cacheKey, Boolean.FALSE);return bean;}
AbstractAdvisorAutoProxyCreator#getAdvicesAndAdvisorsForBean()
方法调用其内部方法findEligibleAdvisors()
去搜索切面,其中又包含了两个步骤,第一步是findCandidateAdvisors()
去搜索候选的切面,第二步是findAdvisorsThatCanApply()
从候选切面中选择能够应用到给定 bean 的切面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;}
搜索候选切面的方法
findCandidateAdvisors()
在AnnotationAwareAspectJAutoProxyCreator
中实现,流程是先调用父类的同名方法初步获取切面列表,然后通过BeanFactoryAspectJAdvisorsBuilder
去创建切面@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;}
BeanFactoryAspectJAdvisorsBuilder#buildAspectJAdvisors()
方法主要流程是首先调用this.advisorFactory.isAspect(beanType)
方法根据注解@Aspect
等条件判断给定bean是否是切面类,其次调用this.advisorFactory.getAdvisors(factory)
去获取增强切面Advisor
public List<Advisor>buildAspectJAdvisors(){ List<String> aspectNames=this.aspectBeanNames;......// 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);if(beanType== null){continue;}if(this.advisorFactory.isAspect(beanType)){ aspectNames.add(beanName); AspectMetadata amd=newAspectMetadata(beanType, beanName);if(amd.getAjType().getPerClause().getKind()== PerClauseKind.SINGLETON){ MetadataAwareAspectInstanceFactory factory=newBeanFactoryAspectInstanceFactory(this.beanFactory, beanName); 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)){thrownewIllegalArgumentException("Bean with name '"+ beanName+"' is a singleton, but aspect instantiation model is not singleton");} MetadataAwareAspectInstanceFactory factory=newPrototypeAspectInstanceFactory(this.beanFactory, beanName);this.aspectFactoryCache.put(beanName, factory); advisors.addAll(this.advisorFactory.getAdvisors(factory));}}}this.aspectBeanNames= aspectNames;return advisors;}}}......}
getAdvisors()
的实现为ReflectiveAspectJAdvisorFactory#getAdvisors()
,该方法会调用getAdvisorMethods(aspectClass)
获取切面类的所有增强方法
,之后调用getAdvisor()
将每个增强方法组装为一个增强切面Advisor
@Overridepublic List<Advisor>getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory){...... List<Advisor> advisors=newArrayList<>();for(Method method:getAdvisorMethods(aspectClass)){ Advisor advisor=getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);if(advisor!= null){ advisors.add(advisor);}}......return advisors;}
getAdvisor()
返回一个InstantiationModelAwarePointcutAdvisorImpl
实例,该实例保存了切面的类名,增强方法的方法名,切入点等信息。切入点AspectJExpressionPointcut
为getPointcut()
返回值,该方法会解析增强方法上的注解@Before
@After
等,将注解的属性保存为切入点表达式
,用于匹配被增强的方法public AdvisorgetAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,int declarationOrderInAspect, String aspectName){validate(aspectInstanceFactory.getAspectMetadata().getAspectClass()