25-Spring源码解析之AOP(4)——创建AOP代理(1)

Spring版本:<version>5.2.1.RELEASE</version>

上一篇:24-Spring源码解析之AOP(3)——解析@Aspect获取增强器

上一篇我们讲完了解析@Aspect注解并获取增强器的时机和如何获取增强器。在获取增强器后,就是开始对创建的Bean进行分析看其是否需要创建对应的AOP代理。

那么本篇文章就开始讲解切面类(LogAspects)和被切面类切入的类(MathCalculator)在创建Bean的时候AnnotationAwareAspectJAutoProxyCreator所作的事情。本篇文章所用例子在文章22-Spring源码解析之AOP(1)——@EnableAspectJAutoProxy注解原理中。

首先我们需要意识到一点:实现AOP功能是AnnotationAwareAspectJAutoProxyCreator实现的,它是通过拦截每个Bean的创建过程,然后对需要增强的Bean进行代理。那么我们就需要弄清楚以下两个事情:

  • AnnotationAwareAspectJAutoProxyCreator在创建Bean的哪个地方进行拦截
  • AnnotationAwareAspectJAutoProxyCreator拦截之后所作的工作有哪些

接下来我们就带着以上两个问题开始阅读本篇文章。

一、Bean的创建过程

文章:23-Spring源码解析之AOP(2)——AnnotationAwareAspectJAutoProxyCreator类源码中我们分析过AnnotationAwareAspectJAutoProxyCreator类的结构,忘记了不要紧,我把结论贴一下:

  • AnnotationAwareAspectJAutoProxyCreator是一个BeanPostProcessor
  • AnnotationAwareAspectJAutoProxyCreator也是一个Ordered
  • AnnotationAwareAspectJAutoProxyCreator还是BeanFactoryAware实现类
    在这里插入图片描述

更具体地,AnnotationAwareAspectJAutoProxyCreator是一个InstantiationAwareBeanPostProcessor


为了更清晰的了解 AnnotationAwareAspectJAutoProxyCreator在创建Bean的哪个地方进行拦截,我们还需要知道SpringBean在创建流程中的哪些地方留给了BeanPostProcessor。下面我把Bean的创建流程总结一下:

在这里插入图片描述
从上幅图片可以看出,在Bean的创建过程中,有6个地方进行了BeanPostProcessor的扩展(红色箭头区域)。(对Bean创建感兴趣的同学可以翻看文章:16-Spring源码解析之Bean的生命周期(1)——doGetBean)。

但是我们知道:AnnotationAwareAspectJAutoProxyCreator是一个InstantiationAwareBeanPostProcessor,所以这6个扩展的地方并不都需要关注,只需要重点关注上图片中黄色箭头所指的5个区域即可。

还记得上篇文章中,解析@Aspect获取增强器的过程是在上述图片中哪个区域吗?是在黄色箭头(1)区域。

接下来我们就开始讲解切面类(LogAspects)和被切面类切入的类(MathCalculator)在创建Bean的时候图一中5个黄色区域所作的事情。

二、创建切面类LogAspects

2.1 箭头(1) resolveBeforeInstantiation

因为在这里会通过for循环执行所有InstantiationAwareBeanPostProcessor类型的的PostProcessorpostProcessBeforeInstantiation方法,这里只关注AnnotationAwareAspectJAutoProxyCreator这个类型的InstantiationAwareBeanPostProcessor

在这里插入图片描述
进入postProcessBeforeInstantiation方法

在这里插入图片描述

只执行了isInfrastructureClass就直接进入下面的方法体,为什么没有执行shouldSkip方法呢?因为,这里isInfrastructureClass直接返回true就不需要执行shouldSkip方法就可以直接进入方法体了。

在方法体中,将logAspects放到advisedBeans中。我们现在可以看看advisedBeans中的值。

在这里插入图片描述
执行完就返回了null

至此,resolveBeforeInstantiation方法关于AOP的功能实现就分析完了,resolveBeforeInstantiation关于AOP就做了一个事情:

  • logAspects放到advisedBeans

2.2 箭头(2) populateBean

下面截取populate方法在图一中箭头2的区域。

在这里插入图片描述
关注上图中if语句,调用InstantiationAwareBeanPostProcessor类的postProcessAfterInstantiation方法。这里的InstantiationAwareBeanPostProcessor类对应的是AnnotationAwareAspectJAutoProxyCreator。我们看一下AnnotationAwareAspectJAutoProxyCreator类的postProcessAfterInstantiation方法实现。

AnnotationAwareAspectJAutoProxyCreator类没有实现该方法,但是其父类AbstractAutoProxyCreator实现了postProcessAfterInstantiation方法。
在这里插入图片描述

从上图可以看出,该方法会永远返回true。所以在populateBean方法的箭头(2) 区域的if语句为false,不会执行if语句体中的语句。所以会继续执行属性赋值。

2.3 箭头(3) populateBean

下面截取populate方法在图一中箭头3的区域。
在这里插入图片描述

我们进入AnnotationAwareAspectJAutoProxyCreator类的postProcessProperties方法实现。

在这里插入图片描述
从上图可以看出,AnnotationAwareAspectJAutoProxyCreator类的父类没有对该方法作特殊的处理,只是直接返回了pvs的值。

2.4 箭头(4) initializeBean

下面截取initializeBean方法在图一中箭头4的区域。
在这里插入图片描述
从上图可以看出,在这里执行BeanPostProcessor的时候,没有判断BeanPostProcessor的具体类型,所以任何类型的BeanPostProcessor都会被执行。

在这里插入图片描述

从上图可以看出,AnnotationAwareAspectJAutoProxyCreator类的父类没有对该方法作特殊的处理,只是直接返回了bean的值。

2.5 箭头(5) initializeBean

下面截取initializeBean方法在图一中箭头5的区域。

在这里插入图片描述

从上图可以看出,在这里执行BeanPostProcessor的时候,没有判断BeanPostProcessor的具体类型,所以任何类型的BeanPostProcessor都会被执行。我们关注当BeanPostProcessorAnnotationAwareAspectJAutoProxyCreator时调用postProcessAfterInitialization的情况。

	public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
		if (bean != null) {
			// 根据给定的bean的class和name构建出一个key,格式 beanClassName_beanName
			// 但是这里因为不是FactoryBean,所以返回的只是beanName
			Object cacheKey = getCacheKey(bean.getClass(), beanName);
			if (this.earlyProxyReferences.remove(cacheKey) != bean) {
// ------------------------------------------核 心--------------------------------------------------
				// 如果它适合被代理,则需要封装这个bean
				return wrapIfNecessary(bean, beanName, cacheKey);
			}
		}
		return bean;
	}
	protected Object getCacheKey(Class<?> beanClass, @Nullable String beanName) {
		if (StringUtils.hasLength(beanName)) {
			return (FactoryBean.class.isAssignableFrom(beanClass) ?
					BeanFactory.FACTORY_BEAN_PREFIX + beanName : beanName);
		}
		else {
			return beanClass;
		}
	}

我们进入wrapIfNecessary方法

在这里插入图片描述
我们在【2.1 箭头(1) resolveBeforeInstantiation】节将logAspects放到advisedBeans中,因此现在advisedBeans中已经有logAspects的值了,所以现在可以根据logAspects键获取他的值,但是这里的值为false,因此在上图中会直接返回bean而不做任何处理。

这里如果不返回,会创建AOP的代理对象!但是我们知道LogAspects是切面类,而不是需要被织入增强器的类。

至此,我们完成了切面类LogAspects对应的Bean的创建。从上面分析可以知道,在创建切面类LogAspects的过程中,与AOP功能有关系的操作只有一个:即在resolveBeforeInstantiation方法中将logAspects放到advisedBeans中。

在这里插入图片描述
即图一中只有上面红色箭头区域做的操作与AOP功能有关。

接下来我们就开始讲解被切面类切入的类(MathCalculator)在创建Bean的时候图一中5个黄色区域所作的事情。

三、切面类切入的类(MathCalculator

3.1 箭头(1) resolveBeforeInstantiation

因为在这里会通过for循环执行所有InstantiationAwareBeanPostProcessor类型的的PostProcessorpostProcessBeforeInstantiation方法,这里只关注AnnotationAwareAspectJAutoProxyCreator这个类型的InstantiationAwareBeanPostProcessor

在这里插入图片描述

进入postProcessBeforeInstantiation方法。

在这里插入图片描述
当前advisedBeans中的值只有两个:

  • mainConfig_AOP -> false
    • 创建 mainConfig_AOPBean的时候放入advisedBeans
  • logAspects -> false
    • 创建 logAspectsBean的时候放入advisedBeans

注意在创建MathCalculator时候的postProcessBeforeInstantiation方法的执行过程与在创建LogAspects时候的postProcessBeforeInstantiation方法的执行过程不同。

在创建LogAspects的时候isInfrastructureClass方法返回值为true,因此不会执行shouldSkip方法直接返回null。在创建MathCalculator的时候isInfrastructureClass方法返回值为false,因此会执行shouldSkip方法。

MainConfig_AOP类对应的Bean创建的时候也进入了shouldSkip方法,那个时候进入shouldSkip方法的目的是:解析@Aspect注解,将注解标注的类的增强器解析出来。

我们进入shouldSkip方法。

在这里插入图片描述
我们进入findCandidateAdvisors方法
在这里插入图片描述
我们继续进入:this.aspectJAdvisorsBuilder.buildAspectJAdvisors()方法

在这里插入图片描述
首先从BeanFactoryAspectJAdvisorsBuilder类的aspectBeanNames属性中获取aspectBeanNames,这个aspectBeanNames值是在解析@Aspect注解的时候放入的。忘记了?没关系,我在贴一次:
在这里插入图片描述
还是这个buildAspectJAdvisors方法,只是在if (aspectNames == null)条件成立的时候放入的。

但是当前aspectNames中的值不为空,它的值为:被注解@Aspets标注的类logAspects对应的beanName。因此不会再进入if (aspectNames == null),而是进入后面的语句。因为被注解@Aspets标注的类可能不止一个,因此我们需要通过for循环遍历每一个被注解@Aspets标注的类。然后根据beanNameadvisorsCache中获取这个Bean的所有增强器。最后将获取到的advisors返回。

返回到我们的shouldSkip方法中,即图二。
在这里插入图片描述
在执行完findCandidateAdvisors方法,返回的值放到candidateAdvisors中。我们遍历获取到的candidateAdvisors。当前candidateAdvisors中有4个增强器。

在这里插入图片描述
但是这些Advisor都不属于AspectJPointcutAdvisor类型的,因此shouldSkip方法返回false。我们回调调用shouldSkip的方法postProcessBeforeInstantiation

在这里插入图片描述
这里targetSource方法返回null,所以postProcessBeforeInstantiation方法会返回null

至此,我们将图一的黄色箭头(1) resolveBeforeInstantiation分析完。而黄色箭头(1) resolveBeforeInstantiation处关于AOP功能似乎什么都没有做。也没有将mathCalculator放到advisedBeans

3.2 箭头(2) populateBean

下面截取populate方法在图一中箭头2的区域。

在这里插入图片描述
关注上图中if语句,调用InstantiationAwareBeanPostProcessor类的postProcessAfterInstantiation方法。这里的InstantiationAwareBeanPostProcessor类对应的是AnnotationAwareAspectJAutoProxyCreator。我们看一下AnnotationAwareAspectJAutoProxyCreator类的postProcessAfterInstantiation方法实现。

AnnotationAwareAspectJAutoProxyCreator类没有实现该方法,但是其父类AbstractAutoProxyCreator实现了postProcessAfterInstantiation方法。
在这里插入图片描述

从上图可以看出,该方法会永远返回true。所以在populateBean方法的箭头(2) 区域的if语句为false,不会执行if语句体中的语句。所以会继续执行属性赋值。

3.3 箭头(3) populateBean

下面截取populate方法在图一中箭头3的区域。
在这里插入图片描述

我们进入AnnotationAwareAspectJAutoProxyCreator类的postProcessProperties方法实现。

在这里插入图片描述
从上图可以看出,AnnotationAwareAspectJAutoProxyCreator类的父类没有对该方法作特殊的处理,只是直接返回了pvs的值。

3.4 箭头(4) initializeBean

下面截取initializeBean方法在图一中箭头4的区域。
在这里插入图片描述
从上图可以看出,在这里执行BeanPostProcessor的时候,没有判断BeanPostProcessor的具体类型,所以任何类型的BeanPostProcessor都会被执行。

在这里插入图片描述

从上图可以看出,AnnotationAwareAspectJAutoProxyCreator类的父类没有对该方法作特殊的处理,只是直接返回了bean的值。

3.5 箭头(5) initializeBean

下面截取initializeBean方法在图一中箭头5的区域。

在这里插入图片描述
我们只关心与AOP功能有关的BeanPostProcessor。因此,我们遍历到BeanPostProcessorAnnotationAwareAspectJAutoProxyCreator。我们进入AnnotationAwareAspectJAutoProxyCreator类的postProcessAfterInitialization方法中。

在这里插入图片描述
我们进入wrapIfNecessary方法。

	protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
		// 已经处理过,则直接返回
		if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
			return bean;
		}
		// 无需增强
		if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
			return bean;
		}
		// 给定的Bean类是否代表一个基础设施类,基础设施类不应被代理,或者配置了指定bean不需要自动代理
		if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
			this.advisedBeans.put(cacheKey, Boolean.FALSE);
			return bean;
		}

		// Create proxy if we have advice.
// ---------------------------------------【功能一】--3.5.1 详细介绍-------------------------------------		
// ----------------------------------核心方法  ----------------------------------
		// 获取增强器并判断获取到的增强器是否适合当前的Bean
		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
		// 如果获取到了增强器则需要针对增强器进行代理
		if (specificInterceptors != DO_NOT_PROXY) {
			this.advisedBeans.put(cacheKey, Boolean.TRUE);
			// 创建代理
// ---------------------------------------【功能二】--3.5.2 详细介绍-------------------------------------			
			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;
	}

在这里插入图片描述
当前advisedBeans中只有2个值。

3.5.1 getAdvicesAndAdvisorsForBean获取增强器

	protected Object[] getAdvicesAndAdvisorsForBean(
			Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
		// 获取到候选的所有增强器
		List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
		if (advisors.isEmpty()) {
			return DO_NOT_PROXY;
		}
		return advisors.toArray();
	}

我们进入findEligibleAdvisors方法

	protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
// ----------------------【功能一】---与3.1 箭头(1) `resolveBeforeInstantiation`一样--------------------	
		// 获取所有的增强器
		List<Advisor> candidateAdvisors = findCandidateAdvisors();
// ---------------------------------------【功能二】----下面详细分析-----------------------------------		
		// 寻找所有增强器中适用于当前Bean的增强器并应用
		List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
		extendAdvisors(eligibleAdvisors);
		if (!eligibleAdvisors.isEmpty()) {
			eligibleAdvisors = sortAdvisors(eligibleAdvisors);
		}
		return eligibleAdvisors;
	}

因为findEligibleAdvisors方法中调用的findCandidateAdvisors方法我们已经分析完了,所以这里就再次赘述了。直接给出执行完findCandidateAdvisors的结果。
在这里插入图片描述
我们带着candidateAdvisors来进入 findEligibleAdvisors方法的【功能二】 findAdvisorsThatCanApply方法

3.5.1.1 findEligibleAdvisors方法的【功能二】 findAdvisorsThatCanApply

该方法的功能:寻找匹配的增强器

前面的函数中已经完成了所有增强器的解析,但是对于所有增强器来讲,并不一定都适用于当前的Bean,还要挑取出适合的增强器,也就是满足我们配置的通配符的增强器。具体实现在findAdvisorsThatCanApply方法中。

	protected List<Advisor> findAdvisorsThatCanApply(
			List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {

		ProxyCreationContext.setCurrentProxiedBeanName(beanName);
		try {
			// 过滤已经得到的advisors
			return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
		}
		finally {
			ProxyCreationContext.setCurrentProxiedBeanName(null);
		}
	}

进入findAdvisorsThatCanApply方法

	public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
		if (candidateAdvisors.isEmpty()) {
			return candidateAdvisors;
		}
		List<Advisor> eligibleAdvisors = new ArrayList<>();
		// 首先处理引介增强,本例子中没有引介增强,这里不具体分析
		for (Advisor candidate : candidateAdvisors) {
			if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
				eligibleAdvisors.add(candidate);
			}
		}
		boolean hasIntroductions = !eligibleAdvisors.isEmpty();
		for (Advisor candidate : candidateAdvisors) {
			// 引介增强已经处理
			if (candidate instanceof IntroductionAdvisor) {
				// already processed
				continue;
			}
// ---------------------------------------核心方法-------------------------------------				
			// 对于普通的Bean的处理
			if (canApply(candidate, clazz, hasIntroductions)) {
				eligibleAdvisors.add(candidate);
			}
		}
		return eligibleAdvisors;
	}

findAdvisorsThatCanApply方法的主要功能是寻找所有增强器中使用与当前bean的增强器。引介增强与普通的增强是处理不一样的,所以分开处理。而对于真正的匹配在canApply实现。

	public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
		if (advisor instanceof IntroductionAdvisor) {
			return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
		}
		// 当前例子的advisor是属于PointcutAdvisor类型
		else if (advisor instanceof PointcutAdvisor) {
			PointcutAdvisor pca = (PointcutAdvisor) advisor;
			return canApply(pca.getPointcut(), targetClass, hasIntroductions);
		}
		else {
			// It doesn't have a pointcut so we assume it applies.
			return true;
		}
	}

我们继续进入canApply方法

	public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
		Assert.notNull(pc, "Pointcut must not be null");
		if (!pc.getClassFilter().matches(targetClass)) {
			return false;
		}
		
		MethodMatcher methodMatcher = pc.getMethodMatcher();
		if (methodMatcher == MethodMatcher.TRUE) {
			// No need to iterate the methods if we're matching any method anyway...
			return true;
		}

		IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
		if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
			introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
		}

		Set<Class<?>> classes = new LinkedHashSet<>();
		if (!Proxy.isProxyClass(targetClass)) {
			classes.add(ClassUtils.getUserClass(targetClass));
		}
		classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));

		for (Class<?> clazz : classes) {	
			// 获取当前类的所有方法
			Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
			for (Method method : methods) {
				// 找到当前类中的方法与增强器方法一样的方法,如果找到了就返回true
				if (introductionAwareMethodMatcher != null ?
						introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
						methodMatcher.matches(method, targetClass)) {
					return true;
				}
			}
		}

		return false;
	}

因为当前类MathCalculatordiv方法是被现有的增强器增强的方法,所以返回true
返回true就说明它找到匹配的增强器了,说明在 3.5.1 getAdvicesAndAdvisorsForBean获取增强器节中返回需要代理。我们一直返回到wrapIfNecessary方法中。

在这里插入图片描述

我们看到执行完Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);方法后,它做了两个事情:

  • this.advisedBeans.put(mathCalculator, Boolean.TRUE);
  • Object proxy = createProxy(....)创建代理

3.5.2 createProxy创建代理

在获取了所有对应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.copyFrom(this);
// ---------------------------------------【功能二】---------------------------------------				
		// 决定对于给定的Bean是否应该使用 targetClass而不是它的接口代理
		// 检查proxyTargetClass设置以及preserveTargetClass属性
		if (!proxyFactory.isProxyTargetClass()) {
			if (shouldProxyTargetClass(beanClass, beanName)) {
				proxyFactory.setProxyTargetClass(true);
			}
			else {
				evaluateProxyInterfaces(beanClass, proxyFactory);
			}
		}
// ---------------------------------------【功能三】--核心--3.5.2.1 详细分析--------------------------------		
		// 使用Advisor封装拦截器
		Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
		// 加入增强器
		proxyFactory.addAdvisors(advisors);

// ---------------------------------------【功能四】---------------------------------------				
		// 设置要代理的类
		proxyFactory.setTargetSource(targetSource);

// ---------------------------------------【功能五】---------------------------------------			
		// 定制代理
		customizeProxyFactory(proxyFactory);

		// 用来控制代理工厂被配置之后,是否还允许修改通知。
		// 缺省值为false(即在代理被配置之后,不允许修改代理的配置)
		proxyFactory.setFrozen(this.freezeProxy);
		if (advisorsPreFiltered()) {
			proxyFactory.setPreFiltered(true);
		}
// ---------------------------------------【功能六】--核心--3.5.2.2 详细分析--------------------------------	
		return proxyFactory.getProxy(getProxyClassLoader());
	}

对于代理类的创建以及处理,Spring委托给了ProxyFactory去处理,而在此函数中主要是对ProxyFactory的初始化操作,进而为真正的创建代理做准备,这些初始化操作包括如下内容:

  • 【功能一】获取当前类中的属性
  • 【功能二】添加代理接口
  • 【功能三】封装Advisor并加入到ProxyFactory
  • 【功能四】设置要代理的类
  • 【功能五】在Spring中还为子类提供了定制的函数customizeProxyFactory,子类可以在此函数中进行对ProxyFactory的进一步封装
  • 【功能六】进行获取代理操作

其中【功能三】封装Advisor并加入到ProxyFactory是一个非常重要的功能。我们接下来看一下Spring是如何通过buildAdvisors来封装拦截器的。

3.5.2.1 buildAdvisors方法

我们先来看一下buildAdvisors方法中传入的参数的值

在这里插入图片描述
我们进入buildAdvisors方法

	protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) {
		// Handle prototypes correctly...
		// 解析注册的所有InterceptorName
		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));
				}
			}
		}
		if (logger.isTraceEnabled()) {
			// 此处处理Log日志省略
			...
		}

		Advisor[] advisors = new Advisor[allInterceptors.size()];
		for (int i = 0; i < allInterceptors.size(); i++) {
// ---------------------------------------核   心------------------------------------------------
			// 拦截器进行封装转化为Advisor		
			advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
		}
		return advisors;
	}

我们进入this.advisorAdapterRegistry.wrap看它是如何封装的

	public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
		// 如果要封装的对象本身就是Advisor类型的那就直接返回
		if (adviceObject instanceof Advisor) {
			return (Advisor) adviceObject;
		}
		// 因为这个封装方法只对Advisor和Advice两个类型的数据有效,因此如果不是这两个类型就不能封装
		if (!(adviceObject instanceof Advice)) {
			throw new UnknownAdviceTypeException(adviceObject);
		}
		
		Advice advice = (Advice) adviceObject;
		// 如果是MethodInterceptor类型,就使用DefaultPointcutAdvisor来封装
		if (advice instanceof MethodInterceptor) {
			// So well-known it doesn't even need an adapter.
			return new DefaultPointcutAdvisor(advice);
		}
		// 如果存在Advisor的适配器那么也同样需要进行封装
		for (AdvisorAdapter adapter : this.adapters) {
			// Check that it is supported.
			if (adapter.supportsAdvice(advice)) {
				return new DefaultPointcutAdvisor(advice);
			}
		}
		throw new UnknownAdviceTypeException(advice);
	}

而本例子中,传入wrap方法的参数就是Advisor类型的(3.5.1节讲过),因此if (adviceObject instanceof Advisor)我为true直接返回。

我们把所有的增强器都封装起来,并将他放到ProxyFactory后,即完成了createProxy方法的【功能三】。我们回到createProxy方法。

3.5.2.2 proxyFactory.getProxy(getProxyClassLoader())方法

createProxy的最后一个功能就是代理的创建与获取。

	protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
			@Nullable Object[] specificInterceptors, TargetSource targetSource) {

		... 
		// 前面的功能省略
		return proxyFactory.getProxy(getProxyClassLoader());
	}

我们进入proxyFactorygetProxy方法

	public Object getProxy(@Nullable ClassLoader classLoader) {
		return createAopProxy().getProxy(classLoader);
	}

具体是如何创建代理并获取代理的我们下一篇文章详细讲解。

四、总结

整篇文章从图一开始讲起,分析切面类LogAspect和被切面类切入的类(MathCalculator)在创建Bean的时候AnnotationAwareAspectJAutoProxyCreator所作的事情。相信从上面的分析中也可以看出,由于AnnotationAwareAspectJAutoProxyCreator是一个BeanPostProcessor,因此任何Bean在创建的时候都会被拦截并且做一些事情。只是对于不同类型的Bean所做的事情不一样而已。我们可以把Bean分成两类来看:

  • 普通Bean -> 非被切面类切入的类

    • 只是在 resolveBeforeInstantiation时将该类对于的BeanName作为键放到了advisors中,值为false
  • 被切面类切入的类

    • resolveBeforeInstantiation时什么都不做
    • initializeBean -> applyBeanPostProcessorsAfterInitialization
      • getAdvicesAndAdvisorsForBean 获取增强器并判断当前Bean是否与增强器相匹配
      • createProxy创建代理

在这里插入图片描述

至此,所有需要创建代理对象的信息已经解析完了,下一篇文章我们开始讲解以下两个问题:

  • Spring是如何通过createAopProxy();方法创建代理
  • Spring是如何通过getProxy(classLoader)方法获取代理
发布了397 篇原创文章 · 获赞 71 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/xiaojie_570/article/details/104847897