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

一、前言

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

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


本文系列:

  1. Spring源码分析十一:@Aspect方式的AOP上篇 - @EnableAspectJAutoProxy
  2. Spring源码分析十二:@Aspect方式的AOP中篇 - getAdvicesAndAdvisorsForBean
  3. Spring源码分析十三:@Aspect方式的AOP下篇 - createProxy
  4. Spring源码分析二十四:cglib 的代理过程

本文衍生篇:

  1. Spring 源码分析衍生篇九 : AOP源码分析 - 基础篇
  2. Spring 源码分析衍生篇十二 :AOP 中的引介增强

补充篇:

  1. Spring 源码分析补充篇三 :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的功能。不过我们可以通过 spring.aop.auto=false 来关闭 Spring 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)
		// 启用了 AspectJ 自动代理
		@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 {
	// 是否代理目标对象:即是否使用cglib 代理
	boolean proxyTargetClass() default false;
	// 是否暴露代理对象
	boolean exposeProxy() default false;

}

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

二、 AspectJAutoProxyRegistrar

在这里插入图片描述
AspectJAutoProxyRegistrar 实现了 ImportBeanDefinitionRegistrar 接口,那么我们自然要看看他的registerBeanDefinitions 方法了,registerBeanDefinitions 方法的作用是在Spring进入下一步动作之前可以添加BeanDefinition,而Spring Aop 在这里将会将自动代理创建器 AbstractAutoProxyCreator添加到Spring容器中,AbstractAutoProxyCreator 是Spring 实现Aop的核心类。(Spring 在 ConfigurationClassPostProcessor 中完成了对 ImportBeanDefinitionRegistrar 接口的处理,主要功能还是将BeanDefinition保存,等待Spring解析加载到容器中。具体可以看 :Spring 源码分析衍生篇七 :ConfigurationClassPostProcessor 上篇)。


下面直接来看 .AspectJAutoProxyRegistrar#registerBeanDefinitions 方法 如下:

	@Override
	public void registerBeanDefinitions(
			AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
		// 如有必要,注册Aspect J注释自动代理创建器。这里注册的自动代理创建器Aop 实现的核心
		// 这里之所以说如有必要,是因为在调用该方法时,容器中可能已经创建了一个自动代理创建器,
		// 如果这个自动代理创建器优先级更高或者与当前需要创建的自动代理创建器是同一类型,则不需要创建。
		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 方法。


我们下面来看一下 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,在 Aop 场景下,Bean 类型为 AnnotationAwareAspectJAutoProxyCreator。到这里我们就可以知道Aop的功能完成肯定是在 AnnotationAwareAspectJAutoProxyCreator 中完成的,因此下面我们开始分析 AnnotationAwareAspectJAutoProxyCreator 的代码。


注:

  1. 这里之所以 beanName (AUTO_PROXY_CREATOR_BEAN_NAME) 和 bean的类型并不相同,是因为这个beanName 特指内部的自动代理创建器,但是自动创建代理器会对应多种不同的实现方式。比如在默认的事务中,注入的bean类型却为InfrastructureAdvisorAutoProxyCreator,而AOP的实现却是 AnnotationAwareAspectJAutoProxyCreator。之所以注册不同是因为实现功能上的区别。对于事务的自动代理创建器来说,他只需要扫描被事务注解修饰的方法,并进行代理。而Spring Aop 则需要根据 @PointCut 注解 来动态的解析代理哪些方法。

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


三、AnnotationAwareAspectJAutoProxyCreator

由于本文主要分析的是 Spring Aop 的过程,所以我们下面还是对 AnnotationAwareAspectJAutoProxyCreator 自动代理创建器进行分析。AnnotationAwareAspectJAutoProxyCreator 本身的逻辑并不多,核心逻辑在其父类AbstractAutoProxyCreator 中。


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

那么我们来看看 AnnotationAwareAspectJAutoProxyCreator ,其主要逻辑实际上还是在其父类 AbstractAutoProxyCreator 中完成。(包括事务的实现逻辑也主要在 AbstractAutoProxyCreator 中,这一点后续关于事务的源码分析: Spring源码分析十四:事务实现① - AutoProxyRegistrar)

在这里插入图片描述
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.
		// 正常来说Aop 的代理创建应当在Bean 创建后再进行代理类,但是这里在Bean创建前就可能进行了代理:
		// 对此,官方注释解释: 如果我们有自定义的TargetSource,请在此处创建代理。抑制目标Bean的不必要的默认实例化:TargetSource将以自定义方式处理目标实例。
		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 方法中。但是在此之前,需要先判断一下当前bean是否需要代理,而这个判断应该在Bean 创建之前进行,即在 postProcessBeforeInstantiation 方法中。我们可以看到关键方法是在于 wrapIfNecessary

不过在此之前我们先来看看 postProcessBeforeInstantiation方法中的一段分析。

1. 是否跳过代理

实际上,并非所有满足织入条件的Bean 都会被代理。基础设施类无法代理,自身也无法代理自身。

我们这一部分主要是用来分析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。即自身不能代理自身。


综上,跳过Aop代理的条件就是:Aop基础设施类或者 代理自身时 会跳过代理


2. AbstractAutoProxyCreator#wrapIfNecessary

上面一步是强行跳过了一部分不能代理的Bean,如果到达这一步说明当前Bean不需要跳过代理,那么则需要判断当前Bean是否满足代理条件。

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

	// org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#wrapIfNecessary
	protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
		// 如果当前bean已经处理过了直接返回
		if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
			return bean;
		}
		// 无需增强。这个在AbstractAutoProxyCreator#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);
		// DO_NOT_PROXY = null。很明显,即使当前Bean 需要进行代理,如果没有增强方法也没必要进行代理
		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);

需要注意的是,上面两句关键语句,在 AbstractAutoProxyCreator#postProcessBeforeInstantiation 中也有过调用

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)引入了AspectJAutoProxyRegistrar3. 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)。
			随后AdvicePointcut会被一起封装成一个Advisor (顾问,也即是Advisor) 。
			也就是说,在这里Spring封装出了Pointcut(实际上是AspectJExpressionPointcut)Advice(这里的Advice根据注解使用的不同分为多个种类,AspectJAroundAdviceAspectJMethodBeforeAdvice)以及
			包含他俩的Advisor(实际上是InstantiationModelAwarePointcutAdvisorImpl)。
			这个过程是在ReflectiveAspectJAdvisorFactory#getAdvisor和InstantiationModelAwarePointcutAdvisorImpl构造函数中完成的。
			这里就动态解析出了@Aspect 注解下的切入点,并被封装成了Advisor集合。假设这里的Advisor集合为Advisors2。
		这两步结束后,就解析出来了当前所有的Advisors =Advisors1 + Advisors2;
		
		注:可以简单的理解为一个Advisor即一个增强操作,一个Advisor包含AdvicePointcutAdvice定义了具体增强操作,如前置,后置,环绕等, 
			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集合,AdvisorsProxyFactory根据情况选择Jdk代理(JdkDynamicAopProxy)或者Cglib代理(ObjenesisCglibAopProxy)来完成创建代理类的操作。
	最终执行的代理方法,实际上都是MethodInterceptor#invoke方法。
	
	这里需要注意的是:对于AspectJAroundAdviceAspectJAfterThrowingAdvice他们直接实现了MethodInterceptor接口,所以可以直接使用,
	但是对于AspectJMethodBeforeAdviceAspectJAfterAdviceAspectJAfterReturningAdvice则需要进行一个适配。
	这个适配的是在创建代理类的过程中。在AdvisedSupport#getInterceptorsAndDynamicInterceptionAdvice方法中完成。
	



简单流程图如下:
在这里插入图片描述


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


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

  • 5
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猫吻鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值