Spring @Aspect 注解创建 AOP 代理对象源码分析

2022-06-28 08:37:39

1. SpringBoot 中代理对象的创建者

Spring 是基于动态代理实现的 aop,其核心在于代理类增强目标类的功能。这样对于每一个目标类,如何创建其代理对象就极为关键。从源码来看,Spring 中代理对象的创建都离不开AnnotationAwareAspectJAutoProxyCreator,这个类实现了BeanPostProcessor接口,会在每个bean实例创建时检查该bean是否需要创建代理,需要的话就创建相应的代理

基于 SpringBoot 的自动配置机制,在注解@EnableAspectJAutoProxy 的定义中会通过@Import(AspectJAutoProxyRegistrar.class) 将注册类引入,而在AspectJAutoProxyRegistrar 的注册 bean 定义方法中会通过代码AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary() 最终将AnnotationAwareAspectJAutoProxyCreator 注册到 bean 工厂中

AnnotationAwareAspectJAutoProxyCreator 的继承结构如下:

在这里插入图片描述

2. 代理对象创建流程

在这里插入图片描述

2.1 代理对象创建者的注册

  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{}}
  2. @EnableAspectJAutoProxy 通过@Import(AspectJAutoProxyRegistrar.class) 引入了注册类AspectJAutoProxyRegistrar

    @Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Import(AspectJAutoProxyRegistrar.class)public @interfaceEnableAspectJAutoProxy{booleanproxyTargetClass()defaultfalse;booleanexposeProxy()defaultfalse;}
  3. 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);}}}
  4. AopConfigUtils#registerAspectJAnnotationAutoProxyCreatorIfNecessary()最终调用到其内部方法registerAspectJAnnotationAutoProxyCreatorIfNecessary(),将AnnotationAwareAspectJAutoProxyCreator bean 定义注册到了 bean 工厂中

    @Nullablepublicstatic BeanDefinitionregisterAspectJAnnotationAutoProxyCreatorIfNecessary(
     		BeanDefinitionRegistry registry,@Nullable Object source){returnregisterOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);}

2.2 代理对象创建的入口

  1. 容器启动的过程中,会在环境准备完成的时候进行 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));}......
  2. 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);}......}
  3. getObjectForBeanInstance() 会判断当前 bean 实例的相关属性,从而决定是否通过方法getObjectFromFactoryBean() 去获取工厂 bean

    protected 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;}
  4. 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;}}
  5. 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;}
  6. 上文已经提及AnnotationAwareAspectJAutoProxyCreator 的继承结构,以上步骤最终会调用到AnnotationAwareAspectJAutoProxyCreator 的超类AbstractAutoProxyCreatorpostProcessAfterInitialization() 方法,在该方法内调用的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 切面的解析与适配

在这里插入图片描述

  1. 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;}
  2. 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;}
  3. 搜索候选切面的方法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;}
  4. 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;}}}......}
  5. 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;}
  6. getAdvisor() 返回一个InstantiationModelAwarePointcutAdvisorImpl实例,该实例保存了切面的类名增强方法的方法名切入点等信息。切入点AspectJExpressionPointcutgetPointcut()返回值,该方法会解析增强方法上的注解@Before@After 等,将注解的属性保存为切入点表达式,用于匹配被增强的方法

    public AdvisorgetAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,int declarationOrderInAspect, String aspectName){validate(aspectInstanceFactory.getAspectMetadata().getAspectClass()
  • 作者:谈谈1974
  • 原文链接:https://blog.csdn.net/weixin_45505313/article/details/103495439
    更新时间:2022-06-28 08:37:39