天天看點

Spring AOP 源碼解析

基本概念

AOP 是面向切面|面向方面程式設計的簡稱,Aspect-Oriented Programming。 Aspect 是一種子產品化機制,是用來描述分散在對象,類,函數中的橫切關注點。從關注點分離出橫切關注點是面向切面的程式設計的核心概念。分離關注點使解決特定領域問題的代碼從業務邏輯中獨立出來,業務邏輯的代碼中不在含有針對特定領域問題的代碼調用,業務邏輯和特定領域的問題的關系通過切面來封裝,維護,這樣原本分散在整個程式中的變動就可以很好的管理起來了。

​ 基礎: 待增強對象或者目标對象

​ 切面: 包含對基礎的增強應用

​ 配置: 可以看成一種編織,通過在AOP體系中提供這個配置環境,将基礎和切面結合起來,進而完成切面對目标對象的編織實作

​ Advice(通知): 定義在連接配接點做什麼,為切面增強提供織入接口。在Spring AOP 中,它主要描述Spring AOP 圍繞方法調用而注入的切面行為。

​ Pointcut(切點):決定Advice通知應該作用于哪個連接配接點,也就是說通過Pointcut來定義需要增強的方法集合。

​ Advisor(通知器):完成對目标方法的切面增強設計(advice)和關注點的設計以後,需要一個對象把它們結合起來,完成這個作用的就是Advisor(通知器)。通過Advisor ,可以定義應該使用那個通知并在哪個關注點使用它。

源碼分析

### 啟動過程

在Sprint Boot 啟動類上加入 注解

@EnableAspectJAutoProxy(proxyTargetClass = true)

,注解源碼為:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import({AspectJAutoProxyRegistrar.class})
public @interface EnableAspectJAutoProxy {
    boolean proxyTargetClass() default false;

    boolean exposeProxy() default false;
}           

​ 該注解使用 @Import 注解引入

AspectJAutoProxyRegistrar

, 跟蹤

AspectJAutoProxyRegistrar

類:

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

    /**
     * Register, escalate, and configure the AspectJ auto proxy creator based on the value
     * of the @{@link EnableAspectJAutoProxy#proxyTargetClass()} attribute on the importing
     * {@code @Configuration} class.
     */
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata , 
                                                                        BeanDefinitionRegistry registry) {
        /* 
        往容器中注入AnnotationAwareAspectJAutoProxyCreator類,bean名稱為 org.springframework.aop.config.internalAutoProxyCreator
        */
        AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
        /*
            讀取主配置類的 EnableAspectJAutoProxy的注解的屬性
        */
        AnnotationAttributes enableAspectJAutoProxy =
                AnnotationConfigUtils.attributesFor(importingClassMetadata,     
                                            EnableAspectJAutoProxy.class);
        if (enableAspectJAutoProxy != null) {
            if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
                AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
            }
            if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
                AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
            }
        }
    }
}           

通過源碼發現,

AspectJAutoProxyRegistrar

類 實作了

ImportBeanDefinitionRegistrar

接口,在容器啟動的時候會調用所有實作

ImportBeanDefinitionRegistrar

的 bean 的

registerBeanDefinitions

方法。在方法内部:

1.調用

org.springframework.aop.config.AopConfigUtils#registerAspectJAnnotationAutoProxyCreatorIfNecessary(org.springframework.beans.factory.support.BeanDefinitionRegistry)

a. 在`registerAspectJAnnotationAutoProxyCreatorIfNecessary` 方法内部:

  public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
    return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, (Object)null);
}
             
  1. 最終調用

    org.springframework.aop.config.AopConfigUtils#registerOrEscalateApcAsRequired

    方法, 參數cls 為

    AnnotationAwareAspectJAutoProxyCreator.class

private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
  Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
  if (registry.containsBeanDefinition(
    "org.springframework.aop.config.internalAutoProxyCreator")) {
      BeanDefinition apcDefinition = registry.getBeanDefinition(
        "org.springframework.aop.config.internalAutoProxyCreator");
      if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
          int currentPriority = findPriorityForClass(
            apcDefinition.getBeanClassName());
          int requiredPriority = findPriorityForClass(cls);
          if (currentPriority < requiredPriority) {
              apcDefinition.setBeanClassName(cls.getName());
          }
      }

      return null;
  } else {
      RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
      beanDefinition.setSource(source);
      beanDefinition.getPropertyValues().add("order", -2147483648);
      beanDefinition.setRole(2);
      registry.registerBeanDefinition(
        "org.springframework.aop.config.internalAutoProxyCreator",   
        beanDefinition);
      return beanDefinition;
  }
}           

在方法内部, 首先檢查容器中是否包含名稱為

org.springframework.aop.config.internalAutoProxyCreator

的bean ,容器第一次啟動總不包含該bean,進入else 邏輯,建立一個

AnnotationAwareAspectJAutoProxyCreator.class

的bean定義,并且注冊bean的名稱為

AnnotationAwareAspectJAutoProxyCreator.class

2.調用

org.springframework.context.annotation.AnnotationConfigUtils#attributesFor(org.springframework.core.type.AnnotatedTypeMetadata, java.lang.Class<?>)

該類主要完成 讀取主配置類的

EnableAspectJAutoProxy

的注解的屬性。 主要檢查

proxyTargetClass

exposeProxy

屬性的值

AnnotationAwareAspectJAutoProxyCreator

在容器啟動的過程中, AOP 向容器中注入了一個

AnnotationAwareAspectJAutoProxyCreator

的 bean , 我們來分析一下這個bean 。

類的繼承體系 :

Spring AOP 源碼解析

通過 類的繼承體系,我們發現

AnnotationAwareAspectJAutoProxyCreator

實作了 BeanFactoryAware ,BeanClassLoaderAware, SmartInstantiationAwareBeanPostProcessor,InstantiationAwareBeanPostProcessor , BeanPostProcessor , BeanClassLoaderAware 等接口 來介入容器啟動過程容Bean的生命周期。

類的接口實作:

Spring AOP 源碼解析

AnnotationAwareAspectJAutoProxyCreator

的接口實作中:

BeanFactoryAware接口:

定義了setBeanFactory 接口, 在容器啟動的時候調用

org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#setBeanFactory

@Override
public void setBeanFactory(BeanFactory beanFactory) {
  // 設定容器
  super.setBeanFactory(beanFactory);
  if (!(beanFactory instanceof ConfigurableListableBeanFactory)) {
  throw new IllegalArgumentException(
  "AdvisorAutoProxyCreator requires a ConfigurableListableBeanFactory: " + beanFactory);
  }
  initBeanFactory((ConfigurableListableBeanFactory) beanFactory);
}

protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    // 建立增強器探索工具
  this.advisorRetrievalHelper = new     BeanFactoryAdvisorRetrievalHelperAdapter(beanFactory);
}           

其中initBeanFactory 最終調用

org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator#initBeanFactory

@Override
protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
  // 調用父類的initBeanFactory方法
  super.initBeanFactory(beanFactory);
  if (this.aspectJAdvisorFactory == null) {
    // 建立Aspect增強器工廠
    this.aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory(beanFactory);
  }
  // 建立一個增強器的建構器
  this.aspectJAdvisorsBuilder =
    new BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory);
}           

InstantiationAwareBeanPostProcessor接口:

我們知道在spring 容器建立任意一個bean的過程中。在

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean

的方法中:

@Override
    protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
            throws BeanCreationException {

        // ... 省略代碼

        try {
            // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
            Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
            if (bean != null) {
                return bean;
            }
        }
        catch (Throwable ex) {
            throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
                    "BeanPostProcessor before instantiation of bean failed", ex);
        }

        Object beanInstance = doCreateBean(beanName, mbdToUse, args);
            //... 省略代碼
    }
           

在調用真正建立bean的方法

doCreateBean

之前, 先調用了

resolveBeforeInstantiation

方法。 我們跟蹤

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation

方法:

protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
  Object bean = null;
  if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
    // Make sure bean class is actually resolved at this point.
    // 當容器中存在InstantiationAwareBeanPostProcessors 時,調用InstantiationAwareBeanPostProcessors 的 postProcessBeforeInstantiation 方法和 postProcessAfterInitialization 方法
    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;
}           

當容器中存在

InstantiationAwareBeanPostProcessors

的bean時

1.先調用

applyBeanPostProcessorsBeforeInstantiation

方法,

2.然後在調用

applyBeanPostProcessorsAfterInitialization

方法

跟蹤

applyBeanPostProcessorsBeforeInstantiation

protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
    // 擷取容器中所有BeanPostProcessor, 若BeanPostProcessor 是InstantiationAwareBeanPostProcessor ,則調用其 postProcessBeforeInstantiation 方法
  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;
}           

applyBeanPostProcessorsBeforeInstantiation

方法内部,首先擷取容器中所有

BeanPostProcessor

BeanPostProcessor

InstantiationAwareBeanPostProcessor

則調用其

postProcessBeforeInstantiation

方法 。

​ 然後我們在容器啟動的時候,在容器中注冊了

AnnotationAwareAspectJAutoProxyCreator

并且這個

bean

實作的

InstantiationAwareBeanPostProcessor

接口,是以在容器建立bean的時候,會觸發

AnnotationAwareAspectJAutoProxyCreator

applyBeanPostProcessorsBeforeInstantiation

方法。

這個是Spring AOP 的真正入口。

接下來我們詳細分析:

org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessBeforeInstantiation

AnnotationAwareAspectJAutoProxyCreator

繼承了

AbstractAutoProxyCreator

postProcessBeforeInstantiation

調用鍊:

Spring AOP 源碼解析

詳細分析:

在postProcessBeforeInstantiation 中查找所有的增強器

org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessBeforeInstantiation

的源碼如下,在容器建立任何一個bean的時候觸發:

public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
  //1.先擷取 bean的key
  Object cacheKey = getCacheKey(beanClass, beanName);
    //2. 判斷bean是否已經處理過,處理過的bean被放入targetSourcedBeans 集合中。
  if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
    //3.判斷是否已經包含bean的增強器
    if (this.advisedBeans.containsKey(cacheKey)) {
      return null;
    }
    //4.判斷bean類型 和 是否應該跳過
    if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
      this.advisedBeans.put(cacheKey, Boolean.FALSE);
      return null;
    }
  }

  // Create proxy here if we have a custom TargetSource.
  // Suppresses unnecessary default instantiation of the target bean:
  // The TargetSource will handle target instances in a custom fashion.
  TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
  if (targetSource != null) {
    if (StringUtils.hasLength(beanName)) {
      this.targetSourcedBeans.add(beanName);
    }
    Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, 
                                                                 beanName, targetSource);
    // 建立代理bean
    Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
    this.proxyTypes.put(cacheKey, proxy.getClass());
    return proxy;
  }

  return null;
}           

1.先擷取 bean的key

2.判斷bean是否已經處理過,處理過的bean被放入targetSourcedBeans 集合中。

3.判斷是否已經包含bean的增強器

4.判斷是否是需要增強的bean

a.判斷bean的類型是否為基礎類:Advice,Pointcut,Advisor,AopInfrastructureBean進入isInfrastructureClass源碼:           
protected boolean isInfrastructureClass(Class<?> beanClass) {
  boolean retVal = Advice.class.isAssignableFrom(beanClass) ||
    Pointcut.class.isAssignableFrom(beanClass) ||
      Advisor.class.isAssignableFrom(beanClass) ||
        AopInfrastructureBean.class.isAssignableFrom(beanClass);
  if (retVal && logger.isTraceEnabled()) {
    logger.trace("");
  }
  return retVal;
}           

b.判斷是否跳過處理,進入shouldSkip方法源碼

@Override
protected boolean shouldSkip(Class<?> beanClass, String beanName) {

// 查找容器中所有的候選的增強器清單
List<Advisor> candidateAdvisors = findCandidateAdvisors();
// 若清單中包含目前bean的增強器,傳回true
for (Advisor advisor : candidateAdvisors) {
  if (advisor instanceof AspectJPointcutAdvisor &&
      ((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
    return true;
  }
}
return super.shouldSkip(beanClass, beanName);
}           

跟蹤findCandidateAdvisors 方法内部:

@Override
protected List<Advisor> findCandidateAdvisors() {
  // Add all the Spring advisors found according to superclass rules.
  // 容器中所有實作Advisor接口的bean元件,熟悉 Spring 事物的都知道,Advisor接口是為Spring事務服務的
  List<Advisor> advisors = super.findCandidateAdvisors();
  // Build Advisors for all AspectJ aspects in the bean factory.
  // 查找容器是标注@Aspect 元件的bean ,并解析bean的标注 @Before, @After, @AfterReturning, @AfterThrowing 的方法,即查找增強器。并加入緩存中。
  if (this.aspectJAdvisorsBuilder != null) {
    advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
  }
  return advisors;
}           

5.後續第一次執行不到

postProcessAfterInitialization

Spring 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;
}           

進入wrapIfNecessary方法:

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
 
  if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
    return bean;
  }
  if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
    return bean;
  }
  // 判斷是否生成代理對象
  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;
}           

跟蹤getAdvicesAndAdvisorsForBean()方法最終調用:org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#findEligibleAdvisors:

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():

@Override
protected List<Advisor> findCandidateAdvisors() {
  // Add all the Spring advisors found according to superclass rules.
  // 查找所有 實作Advisor的接口的增強器
  List<Advisor> advisors = super.findCandidateAdvisors();
  // Build Advisors for all AspectJ aspects in the bean factory.
  if (this.aspectJAdvisorsBuilder != null) {
    // 查找所有Aspect ,查找容器是标注@Aspect 元件的bean ,并解析bean的标注 @Before, @After, @AfterReturning, @AfterThrowing 的方法,即查找增強器。并加入緩存中。
    advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
  }
  return advisors;
}           

跟蹤:findAdvisorsThatCanApply 并最終調用: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 processed
      continue;
    }
    if (canApply(candidate, clazz, hasIntroductions)) {
      eligibleAdvisors.add(candidate);
    }
  }
  return eligibleAdvisors;
}           

進入 canApply方法: 最終調用: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;
}           

getAdvicesAndAdvisorsForBean 方法邏輯分析結束。

跟蹤createProxy 方法: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);
    // 設定使用JDK代理還是使用CGLIB代理
  if (!proxyFactory.isProxyTargetClass()) {
    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);
  }
    // 建立代理對象, 代理對象持有 增強器。
  return proxyFactory.getProxy(getProxyClassLoader());
}           

這樣 postProcessAfterInitialization 的邏輯就分析。

總結

在分析了Spring AOP的啟動過程,總結一下總體過程:

1.setBeanFacotry 接口,在容器啟動的時候,建立了 BeanFactoryAdvisorRetrievalHelperAdapter 增強器探索更具和BeanFactoryAspectJAdvisorsBuilderAdapter 增強器的建構器

2.postProcessBeforeInstantiation 接口: 查找所有的切面和Advisor,并将切面的通知解析,建構成初步的增強器,加入到緩存中來。

3.postProcessAfterInitialization 接口,從緩存取出所有的将所有的增強器,建立代理工廠,并織入增強器,建立代理對象

調用過程:

待更新...