Spring Aop 動態代理詳解(jdk與cglib)

前面通過四篇文章講了代理

包括靜態代理jdk動態代理cglib動態代理jdk與cglib動態代理比較,比較詳細的瞭解了兩者的用法以及源碼,知道了兩者的機制,接下來我們要分析的spring aop 算是一個動態代理的具體例子,實際去看看動態代理是如何使用的

本文的目標

1、spring aop在什麼情況下使用jdk動態代理,什麼時候使用cglib動態代理

2、增強邏輯是如何生成的

例子

注:本文的例子是基於springboot搭建的

pom文件,添加如下依賴

<dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

目標類Hello

@Component
public class Hello {
    public void sayHello(){
        System.out.println("hello");
    }
}

切面類AspectJTest,主要有前置、後置和環繞通知

@Aspect
@Component
public class AspectJTest {
    @Pointcut("execution(* *.sayHello(..))")
    public void one(){

    }
    @Before("one()")
    public void beforeHello(){
        System.out.println("beforeHello");
    }

    @After("one()")
    public void afterHello(){
        System.out.println("afterHello");
    }


    @Around("one()")
    public Object aroundHello(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("beforeHello1");
        Object o = joinPoint.proceed();
        System.out.println("afterHello1");
        return o;
    }
}

測試ControllerTest

@Controller
public class ControllerTest {

    @Autowired
    private Hello hello;

    @RequestMapping("/mytest")
    @ResponseBody
    public String test(){
        hello.sayHello();
        return "success";
    }

}

啓動類

@SpringBootApplication
public class LcnManagerApplication {
    public static void main(String[] args) {

        SpringApplication.run(LcnManagerApplication.class, args);

    }
}

啓動後訪問http://localhost:8080/mytest

打印結果

以上是spring aop 基於註解的寫法

下面我們一步一步去分析

由於我們使用的是spring boot ,僅僅添加了一個starter ,我們查看auto包下的spring.factories 文件發現配置了Aop自動配置類

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration

我們的入口就在這個類AopAutoConfiguration,其代碼如下

@Configuration
//我們加入了aop依賴,這幾個類都是存在的
@ConditionalOnClass({ EnableAspectJAutoProxy.class, Aspect.class, Advice.class,
		AnnotatedElement.class })
//我們配置文件中沒有配置spring.aop.auto屬性,但是matchIfMissing爲true還是可以加載此配置類的
@ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true)
public class AopAutoConfiguration {

	@Configuration
	@EnableAspectJAutoProxy(proxyTargetClass = false)
    //我們沒有配置spring.aop.proxy-target-class,但是matchIfMissing爲false此配置類不加載
	@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false", matchIfMissing = false)
	public static class JdkDynamicAutoProxyConfiguration {

	}

	@Configuration
	@EnableAspectJAutoProxy(proxyTargetClass = true)
    //我們沒有配置spring.aop.proxy-target-class,但是matchIfMissing爲true加載此配置類
	@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true", matchIfMissing = true)
	public static class CglibAutoProxyConfiguration {

	}

}

這是個配置類,有兩個註解管控次配置類是否生效@ConditionalOnClass與@ConditionalOnProperty

1、@ConditionalOnClass註解表明,只有{EnableAspectJAutoProxy.class, Aspect.class, Advice.class, AnnotatedElement.class 

這幾個類都存在的情況下,才能生效,我們再pom文件中加入了aop依賴,這幾個類都是存在的

2、@ConditionalOnProperty註解表明,只有配置文件中存在某個參數,並且匹配上才能加載此類

這裏有幾個參數:

prefix:配置前綴

name:配置名

havingValue:如果name屬性存在,則和此值比較,相同返回true

matchIfMissing:如果配置中沒有指定的name屬性,是否允許加載此配置類,true表示允許,false表示不允許。

eg:我們實際解釋下@ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true)

首先判斷配置文件中是否存在spring.aop.auto屬性,如果存在,其值是否爲havingValue,如果和havingValue一致則加載此配置,如果不一致則不加載;如果配置文件中spring.aop.auto屬性都沒有,則看matchIfMissing屬性的值,如果爲true則加載此配置類,如果爲false則不加載此配置類。

此處兩個註解都是true所以AopAutoConfiguration配置類加載

AopAutoConfiguration加載後,內部有兩個靜態內部類,其主要用於啓用@EnableAspectJAutoProxy註解,區別在於參數proxyTargetClass不一致。

兩個內部類的@ConditionalOnProperty註解參數不一樣,最終加載的是CglibAutoProxyConfiguration 配置,啓動註解@EnableAspectJAutoProxy並且參數proxyTargetClass 爲true。

注:所以我們再使用aop時(springboot),不一定需要顯示的用@EnableAspectJAutoProxy註解

我肯看下@EnableAspectJAutoProxy,代碼如下

@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {

	//是否開啓基於類(cglib)的代理,默認爲false(false表示基於jdk的代理),
	boolean proxyTargetClass() default false;

	//是否暴露代理,默認爲false
	boolean exposeProxy() default false;

}

這個註解有兩個參數,重點關注proxyTargetClass這在我們傳遞的參數是true,所以在spring boot中默認開啓的是基於類的cglib代理模式。

我們繼續看AspectJAutoProxyRegistrar類,主要作用就是根據@EnableAspectJAutoProxy註解,用BeanDefinitionRegistry 註冊AnnotationAwareAspectJAutoProxyCreator類

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

	//根據@EnableAspectJAutoProxy的proxytargetclass屬性註冊、升級、配置 
       //AnnotationAwareAspectJAutoProxyCreator
	@Override
	public void registerBeanDefinitions(
			AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        //註冊
		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);
			}
		}
	}

}

我們一步一步看

1、註冊或升級AnnotationAwareAspectJAutoProxyCreator

通過類的名稱我們可以想象出,此類是代理的創建者,基本上也是這樣aop的實現基本都是靠此類完成的,我們跟進代碼

public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
		return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);
}


public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
			BeanDefinitionRegistry registry, @Nullable Object source) {
        //我們看到註冊的類是AnnotationAwareAspectJAutoProxyCreator
        return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class,
 registry, source);
	}


private static BeanDefinition registerOrEscalateApcAsRequired(
			Class<?> cls, BeanDefinitionRegistry registry, @Nullable 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;
		}
        //根據AnnotationAwareAspectJAutoProxyCreator構造beandefinition,然後註冊
		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構造beandefinition,然後用BeanDefinitionRegistry 註冊到容器中

2、爲AnnotationAwareAspectJAutoProxyCreator的beandefinition設置proxytargetclass與exposeProxy屬性

public static void forceAutoProxyCreatorToUseClassProxying(BeanDefinitionRegistry registry) {
		if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
			BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
			definition.getPropertyValues().add("proxyTargetClass", Boolean.TRUE);
		}
	}

	public static void forceAutoProxyCreatorToExposeProxy(BeanDefinitionRegistry registry) {
		if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
			BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
			definition.getPropertyValues().add("exposeProxy", Boolean.TRUE);
		}
	}

其實就是set屬性,前面說過了proxytargetclass爲true,exposeProxy爲false

下面開始講解AnnotationAwareAspectJAutoProxyCreator

首先看下AnnotationAwareAspectJAutoProxyCreator類的層次結構

紅色框是自動代理的創建類的繼承邏輯,基本上Aop的操作都在裏面,又實現了接口BeanPostProcessor與接口InstantiationAwareBeanPostProcessor,使得該類在實例化前後與初始化前後做了一些操作(先進行實例化,然後再初始化),這些操作完成了代理生成、增強邏輯的生成等。

實例化前後和初始化前後的方法都在類AbstractAutoProxyCreator中

我們先從postProcessBeforeInstantiation開始,代碼如下

其中advisedBeans是個map,value爲false時表示不需要代理,爲true表示可以代理

public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
		Object cacheKey = getCacheKey(beanClass, beanName);
        
		if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
			if (this.advisedBeans.containsKey(cacheKey)) {
				return null;
			}
            //目標類是否爲基礎設施類,基礎類不代理,或者設定了bean不需要代理。
			if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
				this.advisedBeans.put(cacheKey, Boolean.FALSE);
				return null;
			}
		}

		//如果我們有設定自己的目標資源,則按照自己的直接創建代理
		TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
		if (targetSource != null) {
			if (StringUtils.hasLength(beanName)) {
				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;
	}

可以看到在實例化之前主要做了兩件事,第一件事判斷當前的bean是否需要代理,代碼如下

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("Did not attempt to auto-proxy infrastructure class [" + beanClass.getName() + "]");
		}
		return retVal;
	}
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
		// 獲取所有增強其,判斷是否需要跳過,一般我們不用
		List<Advisor> candidateAdvisors = findCandidateAdvisors();
		for (Advisor advisor : candidateAdvisors) {
			if (advisor instanceof AspectJPointcutAdvisor &&
					((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
				return true;
			}
		}
        //調用父類,這裏直接返回了false
		return super.shouldSkip(beanClass, beanName);
	}

第二件事,我們自己定義了TargetSource則按我們定義的取創建代理

我們具體的邏輯在這裏沒有看到

接下來是postProcessAfterInstantiation方法,這個方法直接返回true,沒有更過的業務

同樣postProcessBeforeInitialization也沒有做太多的處理直接返回的bean

重要的邏輯都在postProcessAfterInitialization方法中

public Object postProcessAfterInitialization(@Nullable 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) {
        //targetSourcedBeans存在beanname,即我們定義了自己的targetsource則直接返回
		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;
		}

		// 獲取所有的增強攔截器
		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、獲取增強攔截器

2、根據獲取的增強攔截器去創建代理

我們先看如何獲取增強攔截器的,方法getAdvicesAndAdvisorsForBean

protected Object[] getAdvicesAndAdvisorsForBean(
			Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
        //獲取所有增強
		List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
        //爲空則返回DO_NOT_PROXY
		if (advisors.isEmpty()) {
			return DO_NOT_PROXY;
		}
		return advisors.toArray();
	}
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
		//獲取增強
                List<Advisor> candidateAdvisors = findCandidateAdvisors();
                //獲取當前bean能應用的增強
		List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
		extendAdvisors(eligibleAdvisors);
		if (!eligibleAdvisors.isEmpty()) {
			eligibleAdvisors = sortAdvisors(eligibleAdvisors);
		}
		return eligibleAdvisors;
	}

重要的方法是findCandidateAdvisors與findAdvisorsThatCanApply

protected List<Advisor> findCandidateAdvisors() {
		// 從父類中加載xml配置形式的aop.
		List<Advisor> advisors = super.findCandidateAdvisors();
		// 註解方式時,這裏可以獲取bean註解增強.
		if (this.aspectJAdvisorsBuilder != null) {
			advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
		}
		return advisors;
	}

其中buildAspectJAdvisors是重點,其對註解的獲取,增強器的獲取都在其中

public List<Advisor> buildAspectJAdvisors() {
	List<String> aspectNames = this.aspectBeanNames;
	if (aspectNames == null) {
		synchronized (this) {
			aspectNames = this.aspectBeanNames;
			if (aspectNames == null) {
				List<Advisor> advisors = new ArrayList<>();
				aspectNames = new ArrayList<>();
                //獲取在容器中的beanname
				String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
						this.beanFactory, Object.class, true, false);
                //遍歷所有的beanname
				for (String beanName : beanNames) {
					if (!isEligibleBean(beanName)) {
						continue;
					}
                    //根據beanname獲取beantype
					Class<?> beanType = this.beanFactory.getType(beanName);
					if (beanType == null) {
						continue;
					}
                    //beantype存在Aspect註解
					if (this.advisorFactory.isAspect(beanType)) {
						aspectNames.add(beanName);
						AspectMetadata amd = new AspectMetadata(beanType, beanName);
						if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
							MetadataAwareAspectInstanceFactory factory =
									new BeanFactoryAspectInstanceFactory(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)) {
								throw new IllegalArgumentException("Bean with name '" + beanName +
										"' is a singleton, but aspect instantiation model is not singleton");
							}
							MetadataAwareAspectInstanceFactory factory =
									new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
							this.aspectFactoryCache.put(beanName, factory);
							advisors.addAll(this.advisorFactory.getAdvisors(factory));
						}
					}
				}
				this.aspectBeanNames = aspectNames;
				return advisors;
			}
		}
	}

	if (aspectNames.isEmpty()) {
		return Collections.emptyList();
	}
     //組裝返貨
	List<Advisor> advisors = new ArrayList<>();
	for (String aspectName : aspectNames) {
		List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
		if (cachedAdvisors != null) {
			advisors.addAll(cachedAdvisors);
		}
		else {
			MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
			advisors.addAll(this.advisorFactory.getAdvisors(factory));
		}
	}
return advisors;		
}

可以看到具體的邏輯的

1、首先獲取所有的beanname

2、根據beanname獲取對應的class(beantype)

3、根據class判斷類中是否存在Aspect註解

4、對存在Aspect的類獲取增強器

獲取增強器的方法是getAdvisors,代碼如下

public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
        //獲取標記了Aspect註解的類
		Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
        //獲取標記了Aspect註解的類名
		String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
		validate(aspectClass);

		
		MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
				new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);

		List<Advisor> advisors = new ArrayList<>();
        //獲取除標註Pointcut的所有方法
		for (Method method : getAdvisorMethods(aspectClass)) {
            //獲取增強器
			Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
			if (advisor != null) {
				advisors.add(advisor);
			}
		}

		// 配置了增強延時初始化
		if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
			Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
			advisors.add(0, instantiationAdvisor);
		}

		// 獲取DeclareParents註解
		for (Field field : aspectClass.getDeclaredFields()) {
			Advisor advisor = getDeclareParentsAdvisor(field);
			if (advisor != null) {
				advisors.add(advisor);
			}
		}

		return advisors;
	}

然後繼續看getAdvisor

public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
			int declarationOrderInAspect, String aspectName) {

		validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
        //切點信息獲取
		AspectJExpressionPointcut expressionPointcut = getPointcut(
				candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
		if (expressionPointcut == null) {
			return null;
		}
        //根據切點信息生成增強器
		return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
				this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
	}

1、切點信息獲取

private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
        //獲取方法上的註解
		AspectJAnnotation<?> aspectJAnnotation =
				AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
		if (aspectJAnnotation == null) {
			return null;
		}
        //封裝
		AspectJExpressionPointcut ajexp =
				new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);
        //爲ajexp 設置表達式,比如我們這得是one()
		ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
		if (this.beanFactory != null) {
			ajexp.setBeanFactory(this.beanFactory);
		}
		return ajexp;
	}

//只搜索這些註解
private static final Class<?>[] ASPECTJ_ANNOTATION_CLASSES = new Class<?>[] {
			Pointcut.class, Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class};
protected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) {
		for (Class<?> clazz : ASPECTJ_ANNOTATION_CLASSES) {
			AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) clazz);
			if (foundAnnotation != null) {
				return foundAnnotation;
			}
		}
		return null;
	}
//獲取指定方法上的註解,並用AspectJAnnotation封裝
private static <A extends Annotation> AspectJAnnotation<A> findAnnotation(Method method, Class<A> toLookFor) {
		A result = AnnotationUtils.findAnnotation(method, toLookFor);
		if (result != null) {
			return new AspectJAnnotation<>(result);
		}
		else {
			return null;
		}
	}

2、根據切點信息生成增強器

new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
				this, aspectInstanceFactory, declarationOrderInAspect, aspectName)
public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
			Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
			MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {

		this.declaredPointcut = declaredPointcut;
		this.declaringClass = aspectJAdviceMethod.getDeclaringClass();
		this.methodName = aspectJAdviceMethod.getName();
		this.parameterTypes = aspectJAdviceMethod.getParameterTypes();
		this.aspectJAdviceMethod = aspectJAdviceMethod;
		this.aspectJAdvisorFactory = aspectJAdvisorFactory;
		this.aspectInstanceFactory = aspectInstanceFactory;
		this.declarationOrder = declarationOrder;
		this.aspectName = aspectName;

		if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
			// Static part of the pointcut is a lazy type.
			Pointcut preInstantiationPointcut = Pointcuts.union(
					aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);

			// Make it dynamic: must mutate from pre-instantiation to post-instantiation state.
			// If it's not a dynamic pointcut, it may be optimized out
			// by the Spring AOP infrastructure after the first evaluation.
			this.pointcut = new PerTargetInstantiationModelPointcut(
					this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory);
			this.lazy = true;
		}
		else {
			// A singleton aspect.
			this.pointcut = this.declaredPointcut;
			this.lazy = false;
            //真正實例化
			this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
		}
	}

可以看到封裝只是簡單地賦值

private Advice instantiateAdvice(AspectJExpressionPointcut pointcut) {
		Advice advice = this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pointcut,
				this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
		return (advice != null ? advice : EMPTY_ADVICE);
	}
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
			MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {

		Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
		validate(candidateAspectClass);

		AspectJAnnotation<?> aspectJAnnotation =
				AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
		if (aspectJAnnotation == null) {
			return null;
		}

		// If we get here, we know we have an AspectJ method.
		// Check that it's an AspectJ-annotated class
		if (!isAspect(candidateAspectClass)) {
			throw new AopConfigException("Advice must be declared inside an aspect type: " +
					"Offending method '" + candidateAdviceMethod + "' in class [" +
					candidateAspectClass.getName() + "]");
		}

		if (logger.isDebugEnabled()) {
			logger.debug("Found AspectJ method: " + candidateAdviceMethod);
		}

		AbstractAspectJAdvice springAdvice;
        //根據不同的註解類型創建不同的增強器
		switch (aspectJAnnotation.getAnnotationType()) {
			case AtPointcut:
				if (logger.isDebugEnabled()) {
					logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
				}
				return null;
			case AtAround:
				springAdvice = new AspectJAroundAdvice(
						candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
				break;
			case AtBefore:
				springAdvice = new AspectJMethodBeforeAdvice(
						candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
				break;
			case AtAfter:
				springAdvice = new AspectJAfterAdvice(
						candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
				break;
			case AtAfterReturning:
				springAdvice = new AspectJAfterReturningAdvice(
						candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
				AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
				if (StringUtils.hasText(afterReturningAnnotation.returning())) {
					springAdvice.setReturningName(afterReturningAnnotation.returning());
				}
				break;
			case AtAfterThrowing:
				springAdvice = new AspectJAfterThrowingAdvice(
						candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
				AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
				if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
					springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
				}
				break;
			default:
				throw new UnsupportedOperationException(
						"Unsupported advice type on method: " + candidateAdviceMethod);
		}

		// Now to configure the advice...
		springAdvice.setAspectName(aspectName);
		springAdvice.setDeclarationOrder(declarationOrder);
		String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
		if (argNames != null) {
			springAdvice.setArgumentNamesFromStringArray(argNames);
		}
		springAdvice.calculateArgumentBindings();

		return springAdvice;
	}

從函數中可以看到spring會根據不同的註解生成不同的增強器,對應關係如下

@Around       AspectJAroundAdvice

@Before        AspectJMethodBeforeAdvice

@After           AspectJAfterAdvice

@AfterReturning         AspectJAfterReturningAdvice

@AfterThrowing          AspectJAfterThrowingAdvice

我們只分析我們例子中用到的 

AspectJAroundAdvice代碼如下,可以看到其實現了MethodInterceptor接口,是個標準的增強器

public class AspectJAroundAdvice extends AbstractAspectJAdvice implements MethodInterceptor, Serializable {

	

	@Override
	public Object invoke(MethodInvocation mi) throws Throwable {
		if (!(mi instanceof ProxyMethodInvocation)) {
			throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
		}
		ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
                //ProceedingJoinPoint 這是@Around註解方法的參數
		ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi);
		JoinPointMatch jpm = getJoinPointMatch(pmi);
		return invokeAdviceMethod(pjp, jpm, null, null);
	}


}
protected Object invokeAdviceMethod(JoinPoint jp, @Nullable JoinPointMatch jpMatch,
			@Nullable Object returnValue, @Nullable Throwable t) throws Throwable {

		return invokeAdviceMethodWithGivenArgs(argBinding(jp, jpMatch, returnValue, t));
	}

	protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable {
		Object[] actualArgs = args;
		if (this.aspectJAdviceMethod.getParameterCount() == 0) {
			actualArgs = null;
		}
		try {
			ReflectionUtils.makeAccessible(this.aspectJAdviceMethod);
			// 利用反射調用增強方法,這裏的actualArgs就是@Around註解方法的參數ProceedingJoinPoint
			return this.aspectJAdviceMethod.invoke(this.aspectInstanceFactory.getAspectInstance(), actualArgs);
		}
		catch (IllegalArgumentException ex) {
			throw new AopInvocationException("Mismatch on arguments to advice method [" +
					this.aspectJAdviceMethod + "]; pointcut expression [" +
					this.pointcut.getPointcutExpression() + "]", ex);
		}
		catch (InvocationTargetException ex) {
			throw ex.getTargetException();
		}
	}

AspectJAfterAdvice代碼如下,也同樣實現了MethodInterceptor,先去執行目標方法再去執行增強方法

public class AspectJAfterAdvice extends AbstractAspectJAdvice
		implements MethodInterceptor, AfterAdvice, Serializable {

	@Override
	public Object invoke(MethodInvocation mi) throws Throwable {
		try {
            //先去執行目標方法
			return mi.proceed();
		}
		finally {
            //再調用增強方法
			invokeAdviceMethod(getJoinPointMatch(), null, null);
		}
	}
}

AspectJMethodBeforeAdvice代碼如下,和以上兩種不太一樣這裏沒有實現MethodInterceptor,而是實現了MethodBeforeAdvice該方法只有一個before方法,調用before方法執行增強邏輯

public class AspectJMethodBeforeAdvice extends AbstractAspectJAdvice implements MethodBeforeAdvice, Serializable {

	@Override
	public void before(Method method, Object[] args, @Nullable Object target) throws Throwable {
		invokeAdviceMethod(getJoinPointMatch(), null, null);
	}
}

但是又是何時調用的before方法呢,其實這裏有個包裝類MethodBeforeAdviceInterceptor代碼如下,實現了MethodInterceptor接口

public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice, Serializable {

	private final MethodBeforeAdvice advice;

	public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
		Assert.notNull(advice, "Advice must not be null");
		this.advice = advice;
	}

	@Override
	public Object invoke(MethodInvocation mi) throws Throwable {
        //執行增強
		this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
        //執行目標方法
		return mi.proceed();
	}
}

可以看到這個類的invoke方法是先執行了增強,然後再執行了目標方法

直到這裏spring 已經把所有的增強器都創建出來了,相當於在前面幾篇文章中我們手寫的幾個類HelloInvocationHandler,CglibProxyIntercepter。

3、根據當前的bean尋找匹配的增強器

在上篇的篇幅我們通過掃描所有的標註了@Aspect的註解的類,解析類中的標註了通知類型的註解,spring通過註解類型創建了不同的增強器,這裏的增強器是整個容器所有的,全部的,還需要爲當前的bean尋找匹配的,比如爲Hello類中的sayHello方法匹配增強器@Around(one())標註的方法,具體做法是拿到你execution(* *.sayHello(..))表達式,去匹配類中的方法匹配返回true

簡單看下代碼

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

4、創建代理

接下來就是要創建代理了

Object proxy = 
    createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
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
		proxyFactory.copyFrom(this);
        //如果是jdk代理,判斷是否設置了preserveTargetClass
		if (!proxyFactory.isProxyTargetClass()) {
            //如果設置了preserveTargetClass爲true,採用cglib代理
			if (shouldProxyTargetClass(beanClass, beanName)) {
				proxyFactory.setProxyTargetClass(true);
			}
			else {
                //否則爲proxyFactory添加接口屬性
				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());
	}

這裏重點在構建增強器與獲取代理,這裏有個疑問我們不是已經構造了所有的增強器了嗎,爲什麼還有構建?

構建Advisor

protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) {
		// 獲取註冊的通用攔截器
		Advisor[] commonInterceptors = resolveInterceptorNames();

		List<Object> allInterceptors = new ArrayList<>();
		if (specificInterceptors != null) {
			allInterceptors.addAll(Arrays.asList(specificInterceptors));
            //通過攔截器不爲空
			if (commonInterceptors.length > 0) {
				if (this.applyCommonInterceptorsFirst) {
					allInterceptors.addAll(0, Arrays.asList(commonInterceptors));
				}
				else {
					allInterceptors.addAll(Arrays.asList(commonInterceptors));
				}
			}
		}
		
		Advisor[] advisors = new Advisor[allInterceptors.size()];
		for (int i = 0; i < allInterceptors.size(); i++) {
            //封裝爲Advisors
			advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
		}
		return advisors;
	}

這裏爲什麼還要封裝呢,因爲我們前面分析的增強器,有些是註解式的,有些是從xml加載的,有些可能是Advisor有些可能是advice類型的這裏爲了統一

public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
		if (adviceObject instanceof Advisor) {
			return (Advisor) adviceObject;
		}
		if (!(adviceObject instanceof Advice)) {
			throw new UnknownAdviceTypeException(adviceObject);
		}
		Advice advice = (Advice) adviceObject;
		if (advice instanceof MethodInterceptor) {
			// So well-known it doesn't even need an adapter.
			return new DefaultPointcutAdvisor(advice);
		}
		for (AdvisorAdapter adapter : this.adapters) {
			// Check that it is supported.
			if (adapter.supportsAdvice(advice)) {
				return new DefaultPointcutAdvisor(advice);
			}
		}
		throw new UnknownAdviceTypeException(advice);
	}

創建代理proxyFactory.getProxy

public Object getProxy(@Nullable ClassLoader classLoader) {
		return createAopProxy().getProxy(classLoader);
	}
protected final synchronized AopProxy createAopProxy() {
		if (!this.active) {
			activate();
		}
		return getAopProxyFactory().createAopProxy(this);
	}
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);
		}
	}

這裏通過代理工廠去創建AopProxy的,AopProxy分爲兩種,一種是jdkProxy,一種是cglibproxy,基本上知道點spring的都會知道這個,或者聽說過。什麼 aop 底層用的jdk動態代理啊,什麼時候用cglib代理啊等等

還記得開始的註解參數proxytargetclass 最爲重要,完全控制着用什麼代理

1、如果目標對象實現了接口,默認情況下會使用jdk代理

2、目標類沒有實現接口,則使用cglib動態代理

然後我們看下,兩者創建代理類的步驟是否和咱們前幾篇講的一致

JdkDynamicAopProxy

public Object getProxy(@Nullable ClassLoader classLoader) {
		if (logger.isDebugEnabled()) {
			logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
		}
		Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
		findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
		return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
	}

可以看到其創建代理的步驟完全按照jdk創建動態代理的步驟一樣,傳入classloader,實現的接口,和增強邏輯,增強邏輯爲this對象,則表明此類實現了InvocationHandler並實現了invoke方法,事實確實是這樣

final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {

invoke方法如下

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		MethodInvocation invocation;
		Object oldProxy = null;
		boolean setProxyContext = false;

		TargetSource targetSource = this.advised.targetSource;
		Object target = null;

		try {
            //equals方法
			if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
				return equals(args[0]);
			}
            //hashcode方法
			else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
				return hashCode();
			}
			else if (method.getDeclaringClass() == DecoratingProxy.class) {

				return AopProxyUtils.ultimateTargetClass(this.advised);
			}
			else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
					method.getDeclaringClass().isAssignableFrom(Advised.class)) {
				return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
			}

			Object retVal;

			if (this.advised.exposeProxy) {
				oldProxy = AopContext.setCurrentProxy(proxy);
				setProxyContext = true;
			}


			target = targetSource.getTarget();
			Class<?> targetClass = (target != null ? target.getClass() : null);

			// 獲取當前方法的攔截器鏈
			List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

		
			if (chain.isEmpty()) {
                //爲空直接調用目標方法
				Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
				retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
			}
			else {
				// ReflectiveMethodInvocation封裝攔截器連
				invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
				// 執行攔截器鏈
				retVal = invocation.proceed();
			}

			// Massage return value if necessary.
			Class<?> returnType = method.getReturnType();
			if (retVal != null && retVal == target &&
					returnType != Object.class && returnType.isInstance(proxy) &&
					!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
				// Special case: it returned "this" and the return type of the method
				// is type-compatible. Note that we can't help if the target sets
				// a reference to itself in another returned object.
				retVal = proxy;
			}
			else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
				throw new AopInvocationException(
						"Null return value from advice does not match primitive return type for: " + method);
			}
			return retVal;
		}
		finally {
			if (target != null && !targetSource.isStatic()) {
				// Must have come from TargetSource.
				targetSource.releaseTarget(target);
			}
			if (setProxyContext) {
				// Restore old proxy.
				AopContext.setCurrentProxy(oldProxy);
			}
		}
	}

invoke方法獲取了當前方法的攔截器鏈,然後封裝爲ReflectiveMethodInvocation,通過ReflectiveMethodInvocation的proceed方法進行攔截器鏈(增強鏈)依次調用.

public Object proceed() throws Throwable {
		//	如果攔截器鏈已經都執行完則執行目標方法
		if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
			return invokeJoinpoint();
		}
        //獲取攔截器中的下一個攔截器
		Object interceptorOrInterceptionAdvice =
				this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
//動態匹配		
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
			// Evaluate dynamic method matcher here: static part will already have
			// been evaluated and found to match.
			InterceptorAndDynamicMethodMatcher dm =
					(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
			if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
				return dm.interceptor.invoke(this);
			}
			else {
				// Dynamic matching failed.
				// Skip this interceptor and invoke the next in the chain.
				return proceed();
			}
		}
		else {
			//普通攔截器去執行攔截器的invoke方法
			return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
		}
	}

這裏的步驟是

1、判斷攔截器是否都執行完,都執行完就去執行目標方法

2、獲取下一個攔截器

3、執行攔截器的invoke方法

CglibAopProxy

public Object getProxy(@Nullable ClassLoader classLoader) {
		if (logger.isDebugEnabled()) {
			logger.debug("Creating CGLIB proxy: target source is " + this.advised.getTargetSource());
		}

		try {
			Class<?> rootClass = this.advised.getTargetClass();
			Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");

			Class<?> proxySuperClass = rootClass;
			if (ClassUtils.isCglibProxyClass(rootClass)) {
				proxySuperClass = rootClass.getSuperclass();
				Class<?>[] additionalInterfaces = rootClass.getInterfaces();
				for (Class<?> additionalInterface : additionalInterfaces) {
					this.advised.addInterface(additionalInterface);
				}
			}

			// Validate the class, writing log messages as necessary.
			validateClassIfNecessary(proxySuperClass, classLoader);

			// cglib動態代理最重要的類
			Enhancer enhancer = createEnhancer();
            
			if (classLoader != null) {
				enhancer.setClassLoader(classLoader);
				if (classLoader instanceof SmartClassLoader &&
						((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
					enhancer.setUseCache(false);
				}
			}
			enhancer.setSuperclass(proxySuperClass);
			enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
			enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
			enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));
            //獲取所有攔截器
			Callback[] callbacks = getCallbacks(rootClass);
			Class<?>[] types = new Class<?>[callbacks.length];
			for (int x = 0; x < types.length; x++) {
				types[x] = callbacks[x].getClass();
			}
			// fixedInterceptorMap only populated at this point, after getCallbacks call above
			enhancer.setCallbackFilter(new ProxyCallbackFilter(
					this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
			enhancer.setCallbackTypes(types);

			// 構建代理
			return createProxyClassAndInstance(enhancer, callbacks);
		}
		catch (CodeGenerationException | IllegalArgumentException ex) {
			throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
					": Common causes of this problem include using a final class or a non-visible class",
					ex);
		}
		catch (Throwable ex) {
			// TargetSource.getTarget() failed
			throw new AopConfigException("Unexpected AOP exception", ex);
		}
	}

以上函數完成了Enhancer 的構建,屬性設置,以及代理的創建。其中最重要的是獲取攔截器

private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
		// Parameters used for optimization choices...
		boolean exposeProxy = this.advised.isExposeProxy();
		boolean isFrozen = this.advised.isFrozen();
		boolean isStatic = this.advised.getTargetSource().isStatic();

		// 用DynamicAdvisedInterceptor封裝advise
		Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);

		// Choose a "straight to target" interceptor. (used for calls that are
		// unadvised but can return this). May be required to expose the proxy.
		Callback targetInterceptor;
		if (exposeProxy) {
			targetInterceptor = (isStatic ?
					new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :
					new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource()));
		}
		else {
			targetInterceptor = (isStatic ?
					new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) :
					new DynamicUnadvisedInterceptor(this.advised.getTargetSource()));
		}

		// Choose a "direct to target" dispatcher (used for
		// unadvised calls to static targets that cannot return this).
		Callback targetDispatcher = (isStatic ?
				new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp());

		Callback[] mainCallbacks = new Callback[] {
                //加入攔截器數組
				aopInterceptor,  // for normal advice
				targetInterceptor,  // invoke target without considering advice, if optimized
				new SerializableNoOp(),  // no override for methods mapped to this
				targetDispatcher, this.advisedDispatcher,
				new EqualsInterceptor(this.advised),
				new HashCodeInterceptor(this.advised)
		};

		Callback[] callbacks;

		// If the target is a static one and the advice chain is frozen,
		// then we can make some optimizations by sending the AOP calls
		// direct to the target using the fixed chain for that method.
		if (isStatic && isFrozen) {
			Method[] methods = rootClass.getMethods();
			Callback[] fixedCallbacks = new Callback[methods.length];
			this.fixedInterceptorMap = new HashMap<>(methods.length);

			// TODO: small memory optimization here (can skip creation for methods with no advice)
			for (int x = 0; x < methods.length; x++) {
				List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(methods[x], rootClass);
				fixedCallbacks[x] = new FixedChainStaticTargetInterceptor(
						chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());
				this.fixedInterceptorMap.put(methods[x].toString(), x);
			}

			// Now copy both the callbacks from mainCallbacks
			// and fixedCallbacks into the callbacks array.
			callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length];
			System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length);
			System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length);
			this.fixedInterceptorOffset = mainCallbacks.length;
		}
		else {
			callbacks = mainCallbacks;
		}
		return callbacks;
	}

這裏用DynamicAdvisedInterceptor封裝了advise,作爲Callback 返回,我們知道在cglib設置增強(Callback )的時候是設置的實現了MethodInterceptor接口的增強類,可以看出DynamicAdvisedInterceptor也同樣實現了MethodInterceptor並且有intercept去調用攔截器
 

public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
			Object oldProxy = null;
			boolean setProxyContext = false;
			Object target = null;
			TargetSource targetSource = this.advised.getTargetSource();
			try {
				if (this.advised.exposeProxy) {
					oldProxy = AopContext.setCurrentProxy(proxy);
					setProxyContext = true;
				}
				
				target = targetSource.getTarget();
				Class<?> targetClass = (target != null ? target.getClass() : null);
                //獲取攔截器鏈
				List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
				Object retVal;
				
				if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
					
					Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
					retVal = methodProxy.invoke(target, argsToUse);
				}
				else {
					//用CglibMethodInvocation封裝攔截器鏈,並執行proceed方法
					retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
				}
				retVal = processReturnType(proxy, target, method, retVal);
				return retVal;
			}
			finally {
				if (target != null && !targetSource.isStatic()) {
					targetSource.releaseTarget(target);
				}
				if (setProxyContext) {
					
					AopContext.setCurrentProxy(oldProxy);
				}
			}
		}

CglibMethodInvocation集成ReflectiveMethodInvocation,proceed方法是一樣的,都是同樣的步驟去調用攔截器-->根據攔截器鏈一個一個去掉用

關於咱們這個例子中是如何執行的呢?

我們的執行結果是這樣的

beforeHello1
beforeHello
hello
afterHello1
afterHello

執行順序是

1、執行@Around 的前環繞

2、執行@Before 

3、執行目標方法

4、執行@Around的後環繞

5、執行@After

這裏有個疑問爲什麼不止@before在前,而是@Around的前環繞之前呢?

首先我們對我們的增強器肯定排序了

排序的代碼在ReflectiveAspectJAdvisorFactory#getAdvisors方法中,這在前面已經解析過了

具體的排序是在getAdvisorMethods方法中

private List<Method> getAdvisorMethods(Class<?> aspectClass) {
		final List<Method> methods = new ArrayList<>();
		ReflectionUtils.doWithMethods(aspectClass, method -> {
			// Exclude pointcuts
			if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
				methods.add(method);
			}
		});
        //對方法排序
		methods.sort(METHOD_COMPARATOR);
		return methods;
	}

排序規則

private static final Comparator<Method> METHOD_COMPARATOR;

	static {
		Comparator<Method> adviceKindComparator = new ConvertingComparator<>(
				new InstanceComparator<>(
						Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class),
				(Converter<Method, Annotation>) method -> {
					AspectJAnnotation<?> annotation =
						AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(method);
					return (annotation != null ? annotation.getAnnotation() : null);
				});
		Comparator<Method> methodNameComparator = new ConvertingComparator<>(Method::getName);
		METHOD_COMPARATOR = adviceKindComparator.thenComparing(methodNameComparator);
	}

可以看到順序是

Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class

所以優先去執行@Around再去執行@Before再去執行的@After

我們有了執行順序,到底是怎麼執行的呢

先去執行@Around對應的增強類是AspectJAroundAdvice,這個類通過反射去調用了切面類的標註的@Around方法,打印beforeHello1,然後調用ProceedingJoinPoint的proceed方法,這個proceed又會調用下一個攔截器@Before對應的MethodBeforeAdviceInterceptor攔截器,然後MethodBeforeAdviceInterceptor調用AspectJMethodBeforeAdvice的before方法打印beforeHello,然後調用MethodInvocation的proceed方法,又會到下一個攔截器,以此類推完成所有的調用,在中間完成對目標方法的調用,然後完成。

總結:

spring Aop 的代碼看完了,有前面幾篇動態代理的基礎這相對比較好理解,下面梳理下所有的步驟

spring 啓動後去掃描容器中的類,找到帶有註解@Aspect的類,解析標註了@Aspect註解的類,跟不不同的方法註解生成不同的增強器,並且按照特定順序排好序。這些增強器再根據當前的bean找到能適用於當前bean的增強器。然後根據參數proxytargetclass的值來創建代理,創建代理後把增強器鏈花,代理去依次調用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章