Spring源码分析十一:@Aspect方式的AOP上篇 - @EnableAspectJAutoProxy

一、前言

本文是笔者阅读Spring源码的记录文章,由于本人技术水平有限,在文章中难免出现错误,如有发现,感谢各位指正。在阅读过程中也创建了一些衍生文章,衍生文章的意义是因为自己在看源码的过程中,部分知识点并不了解或者对某些知识点产生了兴趣,所以为了更好的阅读源码,所以开设了衍生篇的文章来更好的对这些知识点进行进一步的学习。

全集目录:Spring源码分析:全集整理


本文系列:
Spring源码分析十一:@Aspect方式的AOP上篇 - @EnableAspectJAutoProxy
Spring源码分析十二:@Aspect方式的AOP中篇 - getAdvicesAndAdvisorsForBean
Spring源码分析十三:@Aspect方式的AOP下篇 - createProxy


本文衍生篇:
Spring 源码分析衍生篇九 : AOP源码分析 - 基础篇


二、简介

Aop 即面向切面编程,而 Aspect 是Aop 思想的一种实现。
并不是所有的AOP框架都相同,它们在连接点模型上可能有强弱之分,有些允许在字段修饰符级别的应用通知,有些只支持方法调用相关的连接点。需要注意的是 Spring 只支持方法级别的连接点。

Spring 提供了4种类型的AOP支持

  • 基于代理的经典Spring Aop
  • 纯Pojo切面
  • @Aspect注解驱动的切面
  • 注入式的Aspectj的切面

前三种都是Spring Aop 实现的变体,Spring Aop 构建在动态代理之上,因此Spring 对Aop的支持局限于方法拦截。

本文分析的是 基于 @Aspect 注解的 Aop 源码。

1. Spring Aop 和 AspectJ 的关系

AspectJ 是一套AOP框架,是对java语言语法和语义的扩展,所以他自己提供了一套关键字,这也就是说,如果在没有安装 AspectJ的情况下,是无法使用 AspectJ 的。而Spring Aop 依赖的是Spring,仅仅能做到方法级别的拦截。所以在Spring中使用 @Aspect 注解实现的AOP 功能,其底层实现还是 Spring Aop。


2. @ApsectJ 的启用 - @EnableAspectJAutoProxy

在使用AspectJ AOP 功能时,我们需要使用注解 @EnableAspectJAutoProxy(proxyTargetClass = true) 来开启Aop 功能。那么我们的分析入口自然是从这个注解开始。

但实际上,启用AOP功能并不需要我们手动去声明。因为在只要我们引入了 SpringAop 对应的依赖,Spring就自动帮我们启用 Aop功能。其原因在 org.springframework.boot.autoconfigure.aop.AopAutoConfiguration 类中,如下,Spring 会将 AopAutoConfiguration 加载作为配置类,其内部类也会加载,默认加载 CglibAutoProxyConfigurationCglibAutoProxyConfiguration 上有 @EnableAspectJAutoProxy(proxyTargetClass = true) 注解,也就达到了默认开始AOP的功能。

@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true)
public class AopAutoConfiguration {
    
    

	@Configuration(proxyBeanMethods = false)
	@ConditionalOnClass(Advice.class)
	static class AspectJAutoProxyingConfiguration {
    
    

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

		}

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

		}

	}

	@Configuration(proxyBeanMethods = false)
	@ConditionalOnMissingClass("org.aspectj.weaver.Advice")
	@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true",
			matchIfMissing = true)
	static class ClassProxyingConfiguration {
    
    

		ClassProxyingConfiguration(BeanFactory beanFactory) {
    
    
			if (beanFactory instanceof BeanDefinitionRegistry) {
    
    
				BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
				AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
				AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
			}
		}

	}

}

不过我们仍旧可以知道,AOP的功能入口在于@EnableAspectJAutoProxy 注解。

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

	boolean proxyTargetClass() default false;

	boolean exposeProxy() default false;

}

分析了这么久的源码,从上面我们可以看到 @EnableAspectJAutoProxy 注解 中使用了 @Import(AspectJAutoProxyRegistrar.class) 注解引入了AspectJAutoProxyRegistrar 类,因此我们下面来看看 AspectJAutoProxyRegistrar 类的实现。

二、 AspectJAutoProxyRegistrar

在这里插入图片描述
AspectJAutoProxyRegistrar 实现了 ImportBeanDefinitionRegistrar 接口,那么我们自然要看看他的registerBeanDefinitions 方法了。(Spring 在 ConfigurationClassPostProcessor 中完成了对 ImportBeanDefinitionRegistrar 接口的处理,主要功能还是将BeanDefinition注入到Spring容器中。具体可以看 :Spring 源码分析衍生篇七 :ConfigurationClassPostProcessor 上篇)。

	/**
	 * 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) {
    
    
		// 如有必要,注册Aspect J注释自动代理创建器
		AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
		// 获取 @EnableAspectJAutoProxy 注解
		AnnotationAttributes enableAspectJAutoProxy =
				AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
		if (enableAspectJAutoProxy != null) {
    
    
			// 解析 proxyTargetClass 属性
			if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
    
    
				AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
			}
			//  解析 exposeProxy 属性
			if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
    
    
				AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
			}
		}
	}

从上面代码我们可以看到,registerBeanDefinitions 方法最主要的功能就是自动代理创建器的注册。(所谓的自动代理创建器,顾名思义就是可以用来自动创建代理的"机器",可以简单理解成Spring 封装的一个创建代理对象的工具类,具有多种实现方式,这个下面会讲。这里使用AOP的实现方式,因此我们来看他的注册过程, 即 AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry); 方法 。


其中 registerAspectJAnnotationAutoProxyCreatorIfNecessary 方法在经历数次跳转后最终调用了 AopConfigUtils#registerOrEscalateApcAsRequired 方法。

上面我们说到自动代理创建器有多种实现方式,但是实际使用只能选择其中一种,所以需要根据优先级来判断使用哪一种。


	public static final String AUTO_PROXY_CREATOR_BEAN_NAME =
			"org.springframework.aop.config.internalAutoProxyCreator";

	private static final List<Class<?>> APC_PRIORITY_LIST = new ArrayList<>(3);

	static {
    
    
		// Set up the escalation list...
		// 事务使用
		APC_PRIORITY_LIST.add(InfrastructureAdvisorAutoProxyCreator.class);
		APC_PRIORITY_LIST.add(AspectJAwareAdvisorAutoProxyCreator.class);
		// Spring aop 使用
		APC_PRIORITY_LIST.add(AnnotationAwareAspectJAutoProxyCreator.class);
	}
			
	// 这里的 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(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) {
    
    
				// 改变bean所对应的className 属性
					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;
	}

	...
	// 可以看到,所谓的优先级顺序实际上是在 APC_PRIORITY_LIST 集合的顺序
	public static void forceAutoProxyCreatorToUseClassProxying(BeanDefinitionRegistry registry) {
    
    
		if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
    
    
			BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
			// 设置 proxyTargetClass 属性
			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);
			// 设置 exposeProxy 属性
			definition.getPropertyValues().add("exposeProxy", Boolean.TRUE);
		}
	}

这里可以看到,整体是注册了一个beanName为“org.springframework.aop.config.internalAutoProxyCreator” 的bean,Bean 类型为 AnnotationAwareAspectJAutoProxyCreator。到这里我们就可以知道Aop的功能完成肯定是在 AnnotationAwareAspectJAutoProxyCreator 中完成的,因此下面我们开始分析 AnnotationAwareAspectJAutoProxyCreator 的代码。


注:

  1. 这里之所以 beanName (AUTO_PROXY_CREATOR_BEAN_NAME) 和 bean的类型并不相同,是因为这个beanName 特指内部的自动代理创建器,但是自动创建代理器会对应多种不同的实现方式。比如在默认的事务中,注入的bean类型却为InfrastructureAdvisorAutoProxyCreator,而AOP的实现却是 AnnotationAwareAspectJAutoProxyCreator

  2. 关于优先级的问题,我们可以看到APC_PRIORITY_LIST 集合的顺序,下标越大,优先级越高。因此可以得知优先级的顺序应该是
    InfrastructureAdvisorAutoProxyCreator < AspectJAwareAdvisorAutoProxyCreator < AnnotationAwareAspectJAutoProxyCreator


三、AnnotationAwareAspectJAutoProxyCreator

上面我们可以看到,整个过程就是将 AnnotationAwareAspectJAutoProxyCreator 注册到 Spring 中并且设置一些属性。

那么我们来看看 AnnotationAwareAspectJAutoProxyCreator ,其主要逻辑实际上还是在其父类 AbstractAutoProxyCreator 中完成。(包括事务的实现逻辑也主要在 AbstractAutoProxyCreator 中,这一点后续关于事务的源码分析会详细解读)

在这里插入图片描述
AnnotationAwareAspectJAutoProxyCreator 实现了 SmartInstantiationAwareBeanPostProcessor接口的方法,SmartInstantiationAwareBeanPostProcessor 接口方法穿插在 Bean初始化的过程中,转念一想,Spring Aop的核心思想就是动态代理,那么必然会在bean初始化的时候"做手脚"。因此我们下面的重心就放在 SmartInstantiationAwareBeanPostProcessor 的方法分析上。


注:关于 后处理器SmartInstantiationAwareBeanPostProcessor 的内容 具体请参考 Spring源码分析衍生篇四:后处理器 BeanPostProcessor


上面也说了,其主要逻辑在AbstractAutoProxyCreator 中实现,这里是在AbstractAutoProxyCreator 中实现的 SmartInstantiationAwareBeanPostProcessor 方法,所以我们下面看的实际是 AbstractAutoProxyCreator 类,


四、AbstractAutoProxyCreator

这里额外提一下,Spring事务的实现也依赖于 AbstractAutoProxyCreator 类,并且逻辑与Aop 的实现基本一致,因为事务的实现的方式也是Aop代理。后面新篇讲到事务时会相信解读。


下面是AbstractAutoProxyCreatorSmartInstantiationAwareBeanPostProcessor 的一些实现方法的实现

	@Override
	@Nullable
	public Class<?> predictBeanType(Class<?> beanClass, String beanName) {
    
    
		// 从代理换缓存中获取代理类型
		if (this.proxyTypes.isEmpty()) {
    
    
			return null;
		}
		Object cacheKey = getCacheKey(beanClass, beanName);
		return this.proxyTypes.get(cacheKey);
	}

	@Override
	@Nullable
	public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) {
    
    
		return null;
	}

	@Override
	public Object getEarlyBeanReference(Object bean, String beanName) {
    
    
		Object cacheKey = getCacheKey(bean.getClass(), beanName);
		this.earlyProxyReferences.put(cacheKey, bean);
		return wrapIfNecessary(bean, beanName, cacheKey);
	}

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

		if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
    
    
			if (this.advisedBeans.containsKey(cacheKey)) {
    
    
				return null;
			}
			// 是基础设施类 || 是被 @Aspect 注解修饰的类。则跳过 Aop代理
			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);
			// 创建代理类
			Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
			this.proxyTypes.put(cacheKey, proxy.getClass());
			return proxy;
		}

		return null;
	}

	@Override
	public boolean postProcessAfterInstantiation(Object bean, String beanName) {
    
    
		return true;
	}

	@Override
	public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
    
    
		return pvs;
	}

	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) {
    
    
		return bean;
	}

	/**
	 * Create a proxy with the configured interceptors if the bean is
	 * identified as one to proxy by the subclass.
	 * @see #getAdvicesAndAdvisorsForBean
	 */
	@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;
	}

我们可以根据 SmartInstantiationAwareBeanPostProcessor 方法的调用顺序进行分析。如果想要生成代理,可以在bean初始化之后。也就是 postProcessBeforeInstantiation 方法中。在 postProcessBeforeInstantiation 方法中我们可以看到关键方法是在于 wrapIfNecessary。不过在此之前我们先来看看 postProcessBeforeInstantiation方法中的一段分析

1. 是否跳过代理

我们这一部分主要是用来分析AbstractAutoProxyCreator#postProcessBeforeInstantiation 中的这一段代码:

	// 是基础设施类 || 是被 @Aspect 注解修饰的类。则跳过 Aop代理
	if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
    
    
		this.advisedBeans.put(cacheKey, Boolean.FALSE);
		return null;
	}

这段代码将在bean加载前判断bean是否交由Aop代理,亦或者换一种说法 : 判断将该Bean交由Spring容器创建还是交由Aop 创建。在实际创建bean代理时候,Spring会根据cacheKey 获取到值,为false则不需要代理。

我们可以看到关键的判断条件就是下面两个:

1.1. isInfrastructureClass(beanClass)

这里我们可以很清楚的看到,如果当前bean是基础类(AdvicePointcutAdvisorAopInfrastructureBean及其子类),则返回true。

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

1.2. shouldSkip(beanClass, beanName)

	protected boolean shouldSkip(Class<?> beanClass, String beanName) {
    
    
		// TODO: Consider optimization by caching the list of the aspect names
		// 寻找所有候选代理增强点。关于这个方法,在后面关于 getAdvicesAndAdvisorsForBean 的文章中会详细分析,这里就不分析
		List<Advisor> candidateAdvisors = findCandidateAdvisors();
		for (Advisor advisor : candidateAdvisors) {
    
    
			// 从前面的代码分析可以看出,如果是Aop 的动态封装都是基于 InstantiationModelAwarePointcutAdvisorImpl 也就是 InstantiationModelAwarePointcutAdvisor,自然是继承PointcutAdvisor
			// 如果 代理类基于 AspectJPointcutAdvisor  && aspectName==beanName,即当前初始化的类是ApspectJ类本身。则返回true,跳过代理
			if (advisor instanceof AspectJPointcutAdvisor &&
					((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
    
    
				return true;
			}
		}
		// 父类shouldSkip 判断了文件是否是 .ORIGINAL 后缀,是则跳过。
		return super.shouldSkip(beanClass, beanName);
	}

关于if语句判断条件:

  1. advisor instanceof AspectJPointcutAdvisor
    基础篇有讲过。Advisor两个子接口PointcutAdvisorIntroductionAdvisor 。IntroductionAdvisor与PointcutAdvisor 最本质上的区别就是,IntroductionAdvisor只能应用于类级别的拦截,只能使用Introduction型的Advice。而不能像PointcutAdvisor那样,可以使用任何类型的Pointcut,以及几乎任何类型的Advice。

    而通过 Spring Aop 动态注入的是 Advisor 默认都是 InstantiationModelAwarePointcutAdvisorImpl 都满此条件。所以这里为false 的情况只有硬编码注入时IntroductionAdvisor 类型的 Advisor ,所以这里基本都会返回true。

  2. ((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) : 这里就是判断beanName 是否是 @Aspect 注解修饰的bean的name。

    那么就可以看出,这里返回ture的条件是 @Apsect 修饰的 AspectJPointcutAdvisor 类。即 被 @ApsectJ 修饰的类会跳过代理


综上,跳过Aop代理的条件就是:Aop基础设施类或者 被@Aspect修饰的类


2. AbstractAutoProxyCreator#wrapIfNecessary

postProcessAfterInitialization 方法中我们可看到关键方法 wrapIfNecessary。
wrapIfNecessary 主要是用来判断当前bean是否需要代理,如果需要,则进行bean封装。

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    
    
		// 如果已经处理过
		if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
    
    
			return bean;
		}
		// 无需增强。这个在postProcessBeforeInstantiation 方法中对 cacheKey 进行了判断缓存,this.advisedBeans.get(cacheKey) 的返回值代表当前bean是否需要aop代理。
		if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
    
    
			return bean;
		}
		// 给定的bean类是否是一个基础设施类(Advice、Pointcut、Advisor、AopInfrastructureBean) || 配置了指定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;
	}

可以很明显的发现下面两个方法是关键。

// 获取适配的增强点
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
// 根据增强点创建对象
Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);

2.1. 获取代理增强点 - getAdvicesAndAdvisorsForBean

篇幅所限,新开文章:Spring源码分析十二:@Aspect方式的AOP中篇 - getAdvicesAndAdvisorsForBean

2.2. 创建代理类 - createProxy

篇幅所限,新开文章: Spring源码分析十三:@Aspect方式的AOP 下篇 - createProxy

五、Spring Aop总结

1. @EnableAspectJAutoProxy (proxyTargetClass = true)开始Aop功能。实际上在引入aspectj包之后, Spring默认会通过AopAutoConfiguration配置类开启AOP功能

2. @EnableAspectJAutoProxy (proxyTargetClass = true)注解通过@Import(AspectJAutoProxyRegistrar.class)引入了AspectJAutoProxyRegistrar类

3. AspectJAutoProxyRegistrar中注册了自动代理创建器AnnotationAwareAspectJAutoProxyCreator。之后的操作都在AnnotationAwareAspectJAutoProxyCreator中进行。

4. AnnotationAwareAspectJAutoProxyCreator实现了SmartInstantiationAwareBeanPostProcessor接口, 所以会在Bean创建的时候,
	发现并记录了合适的所有的Advisor并进行拦截代理。

	4.1. 发现所有的Advisor : 这里分为两步。
		第一步是扫描BeanFactory中的所有Advisor类型的bean。这里直接通过BeanFactory获取即可。假设这里获取到的Advisor集合为Advisors1。 
		第二步则是通过扫描@Aspect注解找到切面类,随后筛选切面类中的方法。找到被@Around@Before等注解修饰的通知(Advice) 进行解析,
			并封装成不同的Advice类型(这里不包括@Pointcut注解的解析), @Pointcut会被解析成切入点(Pointcut类)。
			随后Advice和Pointcut会被一起封装成一个Advisor (顾问,也即是Advisor) 。
			也就是说,在这里Spring封装出了Pointcut类(实际上是AspectJExpressionPointcut)和
			Advice类(这里的Advice根据注解使用的不同分为多个种类,如AspectJAroundAdvice、AspectJMethodBeforeAdvice等)以及
			包含他俩的Advisor(实际上是InstantiationModelAwarePointcutAdvisorImpl)。
			这个过程是在ReflectiveAspectJAdvisorFactory#getAdvisor和InstantiationModelAwarePointcutAdvisorImpl构造函数中完成的。
			这里就动态解析出了@Aspect 注解下的切入点,并被封装成了Advisor集合。假设这里的Advisor集合为Advisors2。
		这两步结束后,就解析出来了当前所有的Advisors =Advisors1 + Advisors2;
		
		注:可以简单的理解为一个Advisor即一个增强操作,一个Adviso包含Advice和Pointcut。
			Advice定义了具体增强操作,如前置,后置,环绕等, 
			Pointcut定义了织入规则,满足规则的bean方法才能被增强。

	4.2. 筛选所有合适的Advisor:上一-步筛选出来的Advisor可能并不适用于当前bean,所以需要筛选出合适于当前bean的Advisor。
		比如@Pointcut ("execution (* com.demo.service.impl.UserServiceImpl.findAll())");切入的是UserServiceImpl,而当前的bean如果是
		RoleServiceImpl就不应该被此Advisor所增强。

 

5. 第四步结束后,这里已经筛选出来了适合当前bean所使用的Advisor,下面需要创建代理类。创建代理则是委托给了ProxyFactory来完成。
   ProxyFactory 使用 Advisor 中的 Advice 创建出来了代理增强类并注入到Spring容器中。

	ProxyFactory中有筛选出来的Advisor集合,即Advisors。
	ProxyFactory根据情况选择Jdk代理(JdkDynamicAopProxy)或者Cglib代理(ObjenesisCglibAopProxy)来完成创建代理类的操作。
	最终执行的代理方法,实际上都是MethodInterceptor#invoke方法。
	
	这里需要注意的是:对于AspectJAroundAdvice、AspectJAfterThrowingAdvice他们直接实现了MethodInterceptor接口,所以可以直接使用,
	但是对于AspectJMethodBeforeAdvice、AspectJAfterAdvice、AspectJAfterReturningAdvice则需要进行一个适配。
	这个适配的是在创建代理类的过程中。在AdvisedSupport#getInterceptorsAndDynamicInterceptionAdvice方法中完成。
	



至此,@Aspect方式的AOP 的源码分析结束。


以上:内容部分参考
《Spring实战》
《Spring源码深度解析》
https://www.cnblogs.com/cheng21553516/p/12190008.html
https://blog.csdn.net/wyl6019/article/details/80136000
如有侵扰,联系删除。 内容仅用于自我记录学习使用。如有错误,欢迎指正

猜你喜欢

转载自blog.csdn.net/qq_36882793/article/details/106745317
今日推荐