SpringAOP分析

hahaeee發表於2018-03-31

概念定義

Advice

定義: 幹什麼

PointCut

定義: 在哪幹

Advisor

定義:組裝Advice和PointCut,在哪裡幹什麼

AOP啟動過程

AopAutoConfiguration

從SpringBoot的aop自動配置開始入手

@Configuration
@ConditionalOnClass({ EnableAspectJAutoProxy.class, Aspect.class, Advice.class })
@ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true)
public class AopAutoConfiguration {

   @Configuration
   @EnableAspectJAutoProxy(proxyTargetClass = false)
   @ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false", matchIfMissing = true)
   public static class JdkDynamicAutoProxyConfiguration {

   }

   @Configuration
   @EnableAspectJAutoProxy(proxyTargetClass = true)
   @ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true", matchIfMissing = false)
   public static class CglibAutoProxyConfiguration {

   }

}
複製程式碼

可以是使用**@EnableAspectJAutoProxy**來開啟aop自動代理

根據spring.aop.proxy-target-class屬性來覺得是否使用cglib生成代理

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

  //是否使用cglib方式生成代理,預設使用jdk代理方式
   boolean proxyTargetClass() default false;

   //TODO 暫時不知道啥用
   boolean exposeProxy() default false;

}
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
  	//通過引數傳入BeanDefinitionRegistry物件,自行註冊需要的BeanDefinition
	@Override
	public void registerBeanDefinitions(
			AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
		//註冊AutoProxyCreator到容器中
		AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
		//解析@EnableAspectJAutoProxy屬性
		AnnotationAttributes enableAspectJAutoProxy =
				AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
      	//使用cglib代理
		if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
			AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
		}
        //TODO 不知道啥用
		if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
			AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
		}
	}
}

#org.springframework.aop.config.AopConfigUtils
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
	return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);
}

public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) {
	return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}

public static final String AUTO_PROXY_CREATOR_BEAN_NAME =
      "org.springframework.aop.config.internalAutoProxyCreator";
private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, Object source) {
  //判斷容器中是否已經註冊AUTO_PROXY_CREATOR_BEAN_NAME
  if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
    //沒啥用,不用看
    ...
      return null;
  }
  //容器中沒有AUTO_PROXY_CREATOR_BEAN_NAME的定義,註冊到容器中
  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;
}
複製程式碼

過程總結:

  1. 註冊org.springframework.aop.config.internalAutoProxyCreator到容器中

注意:org.springframework.aop.config.internalAutoProxyCreator只是BeanDefintion的名字而已,不是一個類名.其對應的真實類是org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator

來看一下AbstractAutoProxyCreator全家福

AbstractAutoProxyCreator

從全家福中我們可以看到AutoProxyCreator實現類大致分為兩種:

  • 基於AOP標準概念(Advice,PointCut)
  • 基於名稱匹配

從上面的全家福中可以看到以上3個都是屬於第一種的,為何AopConfigUtils只提供了這3中AutoProxyCreator的註冊? TODO暫時給不出解釋

代理建立過程

猜測:代理物件的建立時機應該是在例項化完成之後找到匹配的切面,然後組裝成一個代理物件

基於這種猜測我們在AbstractAutoProxyCreator中找到對BeanPostProcessor.postProcessAfterInitialization()的實現

AbstractAutoProxyCreator是個抽象類,並實現了幾個Spring生命週期方法(模板方法模式)

#AbstractAutoProxyCreator
//物件例項化完成之後呼叫
@Override
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;
}

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
  //抽象,匹配切面 
  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;
}
複製程式碼

過程總結:

  1. 得到匹配的Advice

    切面匹配過程,下面會詳細講

  2. 織入Advice,生成代理

    protected Object createProxy(
    		Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
      ProxyFactory proxyFactory = new ProxyFactory();
      proxyFactory.copyFrom(this);
    
      //是否使用cglib生成代理
      if (shouldProxyTargetClass(beanClass, beanName)) {
        proxyFactory.setProxyTargetClass(true);
      }
      //新增Advisor
      Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
      for (Advisor advisor : advisors) {
        proxyFactory.addAdvisor(advisor);
      }
      //建立代理
      return proxyFactory.getProxy(getProxyClassLoader());
    }
    protected Advisor[] buildAdvisors(String beanName, Object[] specificInterceptors) {
      //公共Interceptor
      Advisor[] commonInterceptors = resolveInterceptorNames();
      //commonInterceptors+specificInterceptors
      List<Object> allInterceptors = new ArrayList<Object>();
      ...
        Advisor[] advisors = new Advisor[allInterceptors.size()];
      ...
        return advisors;
    }
    
    #org.springframework.aop.framework.ProxyFactory
    public Object getProxy(ClassLoader classLoader) {
       return createAopProxy().getProxy(classLoader);
    }
    
    #org.springframework.aop.framework.ProxyCreatorSupport
    protected final synchronized AopProxy createAopProxy() {
    	...
      return getAopProxyFactory().createAopProxy(this);
    }
    
    #org.springframework.aop.framework.DefaultAopProxyFactory
    public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
    	//是否使用cglib進行代理
    	if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
    	    Class<?> targetClass = config.getTargetClass();
       		if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
       		return new JdkDynamicAopProxy(config);
        	}
             //cglib代理
    		return new ObjenesisCglibAopProxy(config);
    	}
        else {
    	    return new JdkDynamicAopProxy(config);
        }
    }
    
    複製程式碼

具體的Proxy物件生成過程我們暫且不看

以上則是AbstractAutoProxyCreator建立代理的過程

下面我們分別來看基於AOP標準和基於名稱匹配的兩大陣營是如何獲取切面的

切面匹配過程

基於AOP標準

#org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator
@Override
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource) {
	List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
	if (advisors.isEmpty()) {
		return DO_NOT_PROXY;
	}
	return advisors.toArray();
}
	
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
  //抽象,獲取可能匹配的Advice
  List<Advisor> candidateAdvisors = findCandidateAdvisors();
  //抽象,獲取合格的Advice
  List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
  extendAdvisors(eligibleAdvisors);
  if (!eligibleAdvisors.isEmpty()) {
    //對Advice進行排序
    eligibleAdvisors = sortAdvisors(eligibleAdvisors);
  }
  return eligibleAdvisors;
}
複製程式碼

基於Advisor介面

#org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator
protected List<Advisor> findCandidateAdvisors() {
	return this.advisorRetrievalHelper.findAdvisorBeans();
}
#org.springframework.aop.framework.autoproxy.BeanFactoryAdvisorRetrievalHelper
public List<Advisor> findAdvisorBeans() {
		//返回所有Advisor介面的實現類
		String[] advisorNames = null;
		...
		advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
						this.beanFactory, Advisor.class, true, false);
		...
		List<Advisor> advisors = new LinkedList<Advisor>();
		for (String name : advisorNames) {
			...
			advisors.add(this.beanFactory.getBean(name, Advisor.class));
			...
		}
		return advisors;
	}
複製程式碼

基於AspectJ註解

#org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator
@Override
protected List<Advisor> findCandidateAdvisors() {
   //獲取基於Advisor介面的實現類
   List<Advisor> advisors = super.findCandidateAdvisors();
   //另加入基於AspectJ註解的Advisor(通過介面卡模式包裝成一個Advisor)
   advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
   return advisors;
}

#org.springframework.aop.aspectj.annotation.BeanFactoryAspectJAdvisorsBuilder
public List<Advisor> buildAspectJAdvisors() {
	//1.從工廠中獲取所有帶有@Aspect註解的實現類
    //2.解析其中所有方法上的註解
    //3.通過介面卡模式包裝成Advisor返回
    
    //過程不過多分析
    ....
     return advisors;
}
複製程式碼

基於名稱匹配

#org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator
@Override
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource) {
   if (this.beanNames != null) {
      for (String mappedName : this.beanNames) {
         //如果匹配則返回
        if(){
          return PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS;
        }
      }
   }
  //名稱不匹配則返回DO_NOT_PROXY標誌位 ,不進行代理
   return DO_NOT_PROXY;
}
複製程式碼

BeanNameAutoProxyCreator只能對所有註冊的BeanName適用相同的Interceptor

相關文章