天天看點

AOP注解執行流程

1、注解工作原理

@EnableAspectJAutoProxy

啟動支援處理标有AspectJ的@Aspect批注的元件,類似于Spring的<aop:aspectj-autoproxy> XML元素中的功能。要在@Configuration類上使用。

注冊BeanName的 internalAutoProxyCreator(AnnotationAwareAspectJAutoProxyCreator.class)的 BeanDefinetion,在執行個體化之前執行傳回代理對象。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {

/**
* 訓示與基于标準Java接口的代理相反,是否要建立基于子類(CGLIB)的代理。預設為false。
*/
boolean proxyTargetClass() default false;

/**
* 訓示代理應由AOP架構作為ThreadLocal公開,以便通過org.springframework.aop.framework.AopContext類進行檢索。預設情況下為關閉,即不保證AopContext通路将正常進行。
*/
boolean exposeProxy() default false;

}

// AspectJAutoProxyRegistrar 
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
AnnotationAttributes enableAspectJAutoProxy = AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
    }
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
    }
  }

}

// org.springframework.aop.config.AopConfigUtils

registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);

private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, Object source) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
int requiredPriority = findPriorityForClass(cls);
if (currentPriority < requiredPriority) {
apcDefinition.setBeanClassName(cls.getName());
      }
    }
return null;
  }
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
return beanDefinition;
}
      
注冊 AnnotationAwareAspectJAutoProxyCreator
@EnableAspectJAutoProxy
    --> @Import(AspectJAutoProxyRegistrar.class) 
    --> AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar
        --> AspectJAutoProxyRegistrar.registerBeanDefinitions
        -- AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
            -- registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
      
AnnotationAwareAspectJAutoProxyCreator 實作 InstantiationAwareBeanPostProcessor,Instantiation執行個體化之前執行。
graph TB
AnnotationAwareAspectJAutoProxyCreator-->AspectJAwareAdvisorAutoProxyCreator
AspectJAwareAdvisorAutoProxyCreator-->AbstractAdvisorAutoProxyCreator
AbstractAdvisorAutoProxyCreator-->AbstractAutoProxyCreator

AbstractAutoProxyCreator-.-SmartInstantiationAwareBeanPostProcessor
AbstractAutoProxyCreator-.-BeanFactoryAware
AbstractAutoProxyCreator-->ProxyProcessorSupport

SmartInstantiationAwareBeanPostProcessor-.-InstantiationAwareBeanPostProcessor
InstantiationAwareBeanPostProcessor-.-BeanPostProcessor
      

3、工作流程

3.1 建立和注冊AnnotationAwareAspectJAutoProxyCreator的過程

  1. 建立ioc容器;
  2. 注冊配置類,調用refresh()重新整理容器;
  1. registerBeanPostProcessors(beanFactory); 注冊bean的後置處理器來友善攔截bean的建立;
  1. 擷取ioc容器已經定義了的需要建立對象的所有BeanPostProcessor;
  2. 注冊BeanPostProcessorChecker,該日志将在以下情況下記錄資訊消息在BeanPostProcessor執行個體化期間(即當一個bean不适合所有BeanPostProcessor處理。
  3. 将BeanPostProcessor按照 PriorityOrdered、Ordered、nonOrdered、MergedBeanDefinitionPostProcessor儲存到priorityOrderedPostProcessors、internalPostProcessors、orderedPostProcessorNames、nonOrderedPostProcessorNames 依次注冊;
  4. 注冊BeanPostProcessor,實際上就是建立BeanPostProcessor對象,儲存在容器中;

    建立 internalAutoProxyCreator 的BeanPostProcessor【AnnotationAwareAspectJAutoProxyCreator】

  1. 建立Bean的執行個體;
  2. populateBean;給bean的各種屬性指派;
  3. initializeBean:初始化bean;
  1. invokeAwareMethods():處理Aware接口的方法回調;
  2. applyBeanPostProcessorsBeforeInitialization():應用後置處理器的postProcessBeforeInitialization();
  3. invokeInitMethods();執行自定義的初始化方法;
  4. applyBeanPostProcessorsAfterInitialization();執行後置處理器的postProcessAfterInitialization();
  1. BeanPostProcessor(AnnotationAwareAspectJAutoProxyCreator)建立成功;--> initBeanFactory():aspectJAdvisorsBuilder = new BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory);
  2. 最後重新注冊用于将内部bean檢測為ApplicationListener的後處理器,将其移到處理器鍊的末尾(用于拾取代理等)。
  3. 把BeanPostProcessor注冊到BeanFactory中;

    beanFactory.addBeanPostProcessor(postProcessor);

  1. finishBeanFactoryInitialization(beanFactory);完成BeanFactory初始化工作;建立剩下的非抽象非懶加載單執行個體bean;
  1. 周遊擷取容器中所有的Bean,依次建立對象getBean(beanName);

    preInstantiateSingletons:getBean --> doGetBean --> getSingleton --> singletonFactory.getObject(); --> createBean --> doCreateBean

  2. createBean
  1. resolveBeforeInstantiation(beanName, mbdToUse); 生成代理對象,為null就繼續執行 doCreateBean建立對象;
  2. doCreateBean AnnotationAwareAspectJAutoProxyCreator注冊流程一緻。
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
// 省略部分代碼 .... 
// 給BeanPostProcessors一個傳回代理而不是目标bean執行個體的機會
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
          }
// 實際建立指定的bean
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
return beanInstance;
          }


// AnnotationAwareAspectJAutoProxyCreator在所有bean建立之前會有一個攔截,InstantiationAwareBeanPostProcessor 實作會調用 
// postProcessBeforeInstantiation()  postProcessAfterInitialization()
// 【createBean:resolveBeforeInstantiation() 實作接口 InstantiationAwareBeanPostProcessor調用,bean執行個體化(doCreateBean)之前執行】
// org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.resolveBeforeInstantiation
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {.
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
                  }
                }
              }
mbd.beforeInstantiationResolved = (bean != null);
            }
return bean;
          }

protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
if (result != null) {
return result;
                }
              }
            }
return null;
          }
      

3.2 AnnotationAwareAspectJAutoProxyCreator【InstantiationAwareBeanPostProcessor】作用;

  1. bean執行個體化之前,調用AnnotationAwareAspectJAutoProxyCreator.postProcessBeforeInstantiation();
// 判斷目前bean是否在advisedBeans中。
// isInfrastructureClass 判斷目前bean是否是基礎類型的Advice、Pointcut、Advisor、AopInfrastructureBean、或者是否是切面(@Aspect);則   this.advisedBeans.put(cacheKey, Boolean.FALSE);傳回NULL;

public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
Object cacheKey = getCacheKey(beanClass, beanName);

if (beanName == null || !this.targetSourcedBeans.contains(beanName)) {
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
            }
// 判斷目前bean是否是基礎類型的Advice、Pointcut、Advisor、AopInfrastructureBean、或者是否是切面(@Aspect),是則傳回 NULL
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
            }
        }


// 如果我們有自定義的TargetSource,請在此處建立代理。
// 禁止目标Bean的不必要的預設執行個體化:
// TargetSource将以自定義方式處理目标執行個體。
if (beanName != null) {
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
this.targetSourcedBeans.add(beanName);
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
            }
        }

return null;
    }
      
  1. bean初始化之後,調用 AnnotationAwareAspectJAutoProxyCreator.postProcessAfterInitialization,目标類傳回代理對象;
  1. getAdvicesAndAdvisorsForBean --> findEligibleAdvisors --> findAdvisorsThatCanApply 查詢符合目标類的AOP攔截器,并對增強器排序;
  2. specificInterceptors != DO_NOT_PROXY,建立代理對象;
  1. 将對應攔截器包裝成 Advisor,儲存進 proxyFactory;
  2. 給容器中傳回目前元件使用cglib增強了的代理對象;
  3. 以後容器中擷取到的就是這個元件的代理對象,執行目标方法的時候,代理對象就會執行通知方法的流程;
// 如果Bean被子類辨別為要代理的bean,則使用配置的攔截器建立代理 AnnotationAwareAspectJAutoProxyCreator.postProcessAfterInitialization
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
return wrapIfNecessary(bean, beanName, cacheKey);
            }
        }
return bean;
    }

// 包裝Bean的代理,或按原樣包裝Raw Bean執行個體
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
return bean;
        }
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
        }
// 判斷目前bean是否是基礎類型的Advice、Pointcut、Advisor、AopInfrastructureBean、或者是否是切面(@Aspect),是則傳回 NULL
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
        }

// 擷取目前bean的所有增強器(通知方法)  Object[]  specificInterceptors
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;
    }


// getAdvicesAndAdvisorsForBean --> findEligibleAdvisors --> findAdvisorsThatCanApply  查詢符合目标類的AOP攔截器
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;
    }


// eligibleAdvisors 可用增強器集合,
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
if (candidateAdvisors.isEmpty()) {
return candidateAdvisors;
        }
List<Advisor> eligibleAdvisors = new LinkedList<Advisor>();
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;
            }
if (canApply(candidate, clazz, hasIntroductions)) {
eligibleAdvisors.add(candidate);
            }
        }
return eligibleAdvisors;
    }

// 建立AOP代理對象
protected Object createProxy(Class<?> beanClass, String beanName, 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()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
            }
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
            }
        }
// 将對應攔截器包裝成Advisor,儲存進proxyFactory;
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
for (Advisor advisor : advisors) {
proxyFactory.addAdvisor(advisor);
        }

proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);

proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
        }

return proxyFactory.getProxy(getProxyClassLoader());
    }   

// DefaultAopProxyFactory.createAopProxy() 使用cglib或者是jdk代理
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
            }
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
            }
return new ObjenesisCglibAopProxy(config);
        }
else {
return new JdkDynamicAopProxy(config);
        }
    }

      

2.3 AOP代理類目标方法執行;

AOP 代理對象資訊(比如增強器,目标對象,xxx;
AOP注解執行流程
  1. org.springframework.aop.framework.CglibAopProxy.intercept();攔截目标方法的執行;
  2. 根據ProxyFactory對象擷取将要執行的目标方法攔截器鍊;

    List

  3. 如果沒有攔截器鍊,直接執行目标方法;

    攔截器鍊(每一個通知方法又被包裝為方法攔截器,利用MethodInterceptor機制)

  4. 如果有攔截器鍊,把需要執行的目标對象,目标方法,

    攔截器鍊等資訊傳入建立一個 CglibMethodInvocation 對象,

    并調用 Object retVal = mi.proceed();

  5. 攔截器鍊的觸發過程;
  1. 如果沒有攔截器執行執行目标方法,或者攔截器的索引和攔截器數組-1大小一樣(指定到了最後一個攔截器)執行目标方法;
  2. 鍊式擷取每一個攔截器,攔截器執行invoke方法,每一個攔截器等待下一個攔截器執行完成傳回以後再來執行;

    攔截器鍊的機制,保證通知方法與目标方法的執行順序;

AOP注解執行流程

3 總結

  1. @EnableAspectJAutoProxy 開啟AOP功能
  2. @EnableAspectJAutoProxy 會給容器中注冊一個元件 AnnotationAwareAspectJAutoProxyCreator
  3. AnnotationAwareAspectJAutoProxyCreator是一個後置處理器;
  4. 容器的建立流程:

    4.1. registerBeanPostProcessors()注冊後置處理器;建立AnnotationAwareAspectJAutoProxyCreator對象

    4.2. finishBeanFactoryInitialization()初始化剩下的單執行個體bean

         4.2.1. 建立業務邏輯元件和切面元件

         4.2.2. AnnotationAwareAspectJAutoProxyCreator攔截元件的建立過程

         4.2.3. 元件建立完之後,判斷元件是否需要增強

              是:切面的通知方法,包裝成增強器(Advisor);給業務邏輯元件建立一個代理對象(cglib);

  5. 執行目标方法:

    5.1 代理對象執行目标方法

    5.2 CglibAopProxy.intercept();

         5.2.1 得到目标方法的攔截器鍊(增強器包裝成攔截器MethodInterceptor)

         5.2.2 利用攔截器的鍊式機制,依次進入每一個攔截器進行執行;

         5.2.3 效果:

              正常執行:前置通知-》目标方法-》後置通知-》傳回通知

              出現異常:前置通知-》目标方法-》後置通知-》異常通知