栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Spring AOP源码分析一

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring AOP源码分析一

我们之前分析了Spring bean创建的核心源码以及Spring相关注解的源码,这一节开始我们就要开始分析Spring AOP的源码,那这个Spring AOP的源码入口在哪里呢?还记得我们分析创建bean核心流程,在创建bean的时候Spring提供了各种bean的后置处理器,我们猜测AOP代理对象可能是通过这些后置处理来创建的,我们现在先看下bean实例化之前Spring为我们提供的后置处理器。我们看下如下代码:

我们可以看到在bean创建之前,提供了一个机会创建生成代理对象,所以我们猜测这个Spring AOP的代理对象,应该是在这个resolveBeforeInstantiation方法中进行创建的。我们到这个resolveBeforeInstantiation方法中看下:

我们发现resolveBeforeInstantiation()方法会先看一下这个bean在实例化之前是够解析过,那么第一次进来的话这个mbd.beforeInstantiationResolved变量为null,所以整个条件为true。接着会判断是否存在实现了InstantiationAwareBeanPostProcessor接口的beanPostProcessor,如果满足这个条件的话,代码会继续往下走,接着就会调用applyBeanPostProcessorsBeforeInstantiation()方法。
我们到方法applyBeanPostProcessorsBeforeInstantiation中看下:

可以看到,这里其实就是调用了一个getBeanPostProcessors()方法获取到了所有的BeanPostProcessor,然后循环调用了BeanPostProcessor的postProcessBeforeInstantiation()方法,也就是实例化前的处理。那到底执行的是哪一个处理器呢?我们看下InstantiationAwareBeanPostProcessor 的子类有哪些?

可以看到 InstantiationAwareBeanPostProcessor 的子类有很多,但是我们找到了一个和AOP有关的类 AnnotationAwareAspectJAutoProxyCreator,这个就是针对AspectJ注解的自动代理创建器。我们到这个类中看下postProcessBeforeInstantiation方法到底做了什么?

public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorAutoProxyCreator {

	@Nullable
	private List includePatterns;

	@Nullable
	private AspectJAdvisorFactory aspectJAdvisorFactory;

	@Nullable
	private BeanFactoryAspectJAdvisorsBuilder aspectJAdvisorsBuilder;


	
	public void setIncludePatterns(List patterns) {
		this.includePatterns = new ArrayList<>(patterns.size());
		for (String patternText : patterns) {
			this.includePatterns.add(Pattern.compile(patternText));
		}
	}

	public void setAspectJAdvisorFactory(AspectJAdvisorFactory aspectJAdvisorFactory) {
		Assert.notNull(aspectJAdvisorFactory, "AspectJAdvisorFactory must not be null");
		this.aspectJAdvisorFactory = aspectJAdvisorFactory;
	}

	@Override
	protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		super.initBeanFactory(beanFactory);
		if (this.aspectJAdvisorFactory == null) {
			this.aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory(beanFactory);
		}
		this.aspectJAdvisorsBuilder =
				new BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory);
	}


	@Override
	protected List findCandidateAdvisors() {
		// Add all the Spring advisors found according to superclass rules.
		List advisors = super.findCandidateAdvisors();
		// Build Advisors for all AspectJ aspects in the bean factory.
		if (this.aspectJAdvisorsBuilder != null) {
			advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
		}
		return advisors;
	}

	@Override
	protected boolean isInfrastructureClass(Class beanClass) {
		// Previously we setProxyTargetClass(true) in the constructor, but that has too
		// broad an impact. Instead we now override isInfrastructureClass to avoid proxying
		// aspects. I'm not entirely happy with that as there is no good reason not
		// to advise aspects, except that it causes advice invocation to go through a
		// proxy, and if the aspect implements e.g the Ordered interface it will be
		// proxied by that interface and fail at runtime as the advice method is not
		// defined on the interface. We could potentially relax the restriction about
		// not advising aspects in the future.
		return (super.isInfrastructureClass(beanClass) ||
				(this.aspectJAdvisorFactory != null && this.aspectJAdvisorFactory.isAspect(beanClass)));
	}

	
	protected boolean isEligibleAspectBean(String beanName) {
		if (this.includePatterns == null) {
			return true;
		}
		else {
			for (Pattern pattern : this.includePatterns) {
				if (pattern.matcher(beanName).matches()) {
					return true;
				}
			}
			return false;
		}
	}


	
	private class BeanFactoryAspectJAdvisorsBuilderAdapter extends BeanFactoryAspectJAdvisorsBuilder {

		public BeanFactoryAspectJAdvisorsBuilderAdapter(
				ListableBeanFactory beanFactory, AspectJAdvisorFactory advisorFactory) {

			super(beanFactory, advisorFactory);
		}

		@Override
		protected boolean isEligibleBean(String beanName) {
			return AnnotationAwareAspectJAutoProxyCreator.this.isEligibleAspectBean(beanName);
		}
	}

}

但是我们在这个类中并没有找到postProcessBeforeInstantiation方法,而AnnotationAwareAspectJAutoProxyCreator 又继承了AspectJAwareAdvisorAutoProxyCreator 对象,所以我们到它的父类AspectJAwareAdvisorAutoProxyCreator 中找一下

我们在这个AspectJAwareAdvisorAutoProxyCreator 中也没有找到该方法,我发现AspectJAwareAdvisorAutoProxyCreator 继续了AbstractAutoProxyCreator类,所以我们继续在AbstractAutoProxyCreator这个类中找一下:

可以看到,我们AbstractAutoProxyCreator类中找到了该方法。
我们在看一下AnnotationAwareAspectJAutoProxyCreator 类的继承关系:

可以发现AnnotationAwareAspectJAutoProxyCreator的父类是AspectJAwareAdvisorAutoProxyCreator,而AspectJAwareAdvisorAutoProxyCreator的父类是AbstractAdvisorAutoProxyCreator,然后AbstractAdvisorAutoProxyCreator的父类才是这个AbstractAutoProxyCreator类。而AnnotationAwareAspectJAutoProxyCreator正是从这个AbstractAutoProxyCreator继承过来了postProcessBeforeInstantiation()方法,也就是说真正的处理逻辑,其实是在AbstractAutoProxyCreator的postProcessBeforeInstantiation()方法中。我们就来看下这个AbstractAutoProxyCreator类的postProcessBeforeInstantiation()方法吧:

看到了非常关键的一行代码TargetSource targetSource = getCustomTargetSource(beanClass, beanName),这行代码上边注释的意思大概是“如果我们指定了targetSource,那么就在这里创建一个代理”,这里我们得到了一个非常关键的信息,那就是只有指定了targetSource才会在这里创建代理。我们一般是不会指定targetSource的,也就是一般是不会在这里创建代理的。由于我们没有指定targetSource,所以getCustomTargetSource(beanClass, beanName)方法得到的targetSource为null,最终这个postProcessBeforeInstantiation()方法返回的是个null,我们现在继续往下看代码:

一般这些beanPostProcessor的postProcessBeforeInstantiation()方法都会返回null。此时发现这个bean为null,那么这个bean != null的条件就不满足,所以这行代码bean = applyBeanPostProcessorsAfterInitialization(bean, beanName)是不会执行的,说白了就是只在特定条件下才会执行,这个特定条件就是我们指定了targetSource的情况。那这个时候resolveBeforeInstantiation()方法就执行完毕了,由于我们没有指定targetSource,所以此时bean为null,因此resolveBeforeInstantiation()方法返回的也是null,如下图:

也就是说此时Object bean = resolveBeforeInstantiation(beanName, mbdToUse)这行代码执行完之后,这个bean为null,那么bean != null的条件就不满足,此时就不会直接返回bean,那这个时候代码就会继续往下运行,那接下来就开始执行Object beanInstance = doCreateBean(beanName, mbdToUse, args)这行代码了,也就是开始正常的进行bean的实例化和初始化过程。这个resolveBeforeInstantiation()方法的意义到底是什么?其实它的意思就是说,如果我们指定了targetSource,那么可以在这里创建一个代理直接返回,就不需要走下边的实例化和初始化阶段了,因为指定了targetSource后,这个bean就由开发人员自己负责完成创建了。而如果没有指定targetSource,那么就按照正常流程往下执行bean的实例化和初始化,说白了就是注释上说的:“给你一个返回代理的机会”。不过一般我们都不会指定targetSource,所以代码会继续往下运行,此时就会来运行doCreateBean()这个方法来创建bean了,那AOP真正的自动代理时机会不会在这个doCreateBean()方法中呢?

我们接着到doCreateBean方法中看下:

我们可以看到在doCreateBean()方法中有这么关键的几步:
1、首先调用createBeanInstance(beanName, mbd, args)创建了一个bean实例。
2、调用applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName)找到了被@Autowired等注解标注的字段和方法, 为下一步的注入做准备。
3、接着调用populateBean(beanName, mbd, instanceWrapper)为bean填充属性。
4、最后调用initializeBean(beanName, exposedObject, mbd)完成bean的初始化。
首先createBeanInstance()被排除,因为根据我们IOC部分的知识知道,这个createBeanInstance()主要就是创建一个bean实例出来,它里边是没有AOP相关的逻辑的。接着是applyMergedBeanDefinitionPostProcessors()和populateBean(),它们都是和属性注入相关的东西,所以这个里面也没有AOP相关的逻辑。所以只剩下了initializeBean(),我们到这个initializeBean 方法中看下:

我们看到了极为关键的两种beanPostProcessor,一个是初始化前处理的beanPostProcessor,另外一个是初始化后处理的beanPostProcessor,我们要找的AOP逻辑极有可能就在这两个beanPostProcessor的其中一个里边。我们就先来看下applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName)里边是怎么玩儿的吧,点进去这个方法后,代码如下:

这里的核心逻辑就是遍历所有的BeanPostProcessor,然后分别调用它们的postProcessBeforeInitialization()方法。在这个方法中也会调用AnnotationAwareAspectJAutoProxyCreator的postProcessBeforeInitialization()方法。我们到这个AnnotationAwareAspectJAutoProxyCreator的postProcessBeforeInitialization方法中看下:

我们同样在AbstractAutoProxyCreator这个类中找到了该方法,但是这个里面什么也没有做。说白了这里根本没有对bean做任何处理,就相当于一个“空实现”,也就是说AOP的逻辑不在初始化前处理中。我们在回到之前的代码:

我们接着来看下这个applyBeanPostProcessorsAfterInitialization()方法,我们看这里:

在这个方法中同样也会调用AnnotationAwareAspectJAutoProxyCreator的postProcessAfterInitialization()方法。我们还是到AbstractAutoProxyCreator这个类中找这个postProcessAfterInitialization方法:

我们发现一行极为关键的代码return wrapIfNecessary(bean, beanName, cacheKey),从名字上来看,这个wrapIfNecessary()方法会对bean进行包装,包装完毕后,直接将包装好的bean给返回了。那wrapIfNecessary()方法在进行包装的时候,会不会就是将普通的bean给包装成了AOP代理呢?那我们现在就点进去wrapIfNecessary()方法看下:

1、首先是Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null),通过这个方法的名字,我们知道,它主要是用来获取当前bean对应的增强。
2、将获取的增强specificInterceptors交给了createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)),而这个createProxy()方法会根据这些增强生成代理对象proxy,最后将这个代理对象proxy返回,这样就将一个普通的bean替换为了AOP代理。
3、如果这个bean没有相应的增强,即specificInterceptors = null时,是不会给这个bean创建AOP代理的。

梳理一下AOP的执行时机:

需要注意的一点就是,当我们指定了targetSource的时候,除了会调用实例化前处理applyBeanPostProcessorsBeforeInstantiation()外,还会调用初始化后处理applyBeanPostProcessorsAfterInitialization(),对应的代码如下:

由于targetSource一般都不会指定,从而导致bean != null不会满足,所以直接跳过了红框中的这行代码。我们发现resolveBeforeInstantiation()和initializeBean()竟然调了相同的方法,那就是applyBeanPostProcessorsAfterInitialization(),而整个创建AOP代理的关键代码就在这个applyBeanPostProcessorsAfterInitialization()中。所以我们现在明白了,不管我们是否指定了targetSource,都会依赖初始化后处理applyBeanPostProcessorsAfterInitialization()来完成AOP代理的创建。

我们通过流程图梳理今天的内容:

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/781390.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号