Spring读源码系列之AOP--07---aop自动代理创建器(拿下AOP的最后一击)

Posted 大忽悠爱忽悠

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring读源码系列之AOP--07---aop自动代理创建器(拿下AOP的最后一击)相关的知识,希望对你有一定的参考价值。

Spring读源码系列之AOP--07---aop自动代理创建器(拿下AOP的最后一击


引子

本系列列举的源码中,很多类没有展开讲,是因为之前的系列文章一直在对aop基础组件进行介绍,因此一定要按照顺序看本系列,否则观看本篇文章的时候,越往后看,越发觉得本文模糊不清,只会粘贴源码,实则不然,因为很多类前文已经讲过,如果本文再展开讲解,那么将无法突出重点

自动代理创建器是spring的aop体系中最重要的一环,也正是因为有他的存在,才让我们使用aop那么方便

先来看看自动代理创建器相关类藏在了哪里:

可以看出来,所有的创建器都是AbstractAutoProxyCreator该抽象类的子类~


当系统比较复杂,或者中需要进行aop进行织入的bean较多时,简单采用ProxyFacotryBean无疑会增加很多工作量(因为每个Bean都得手动写一个)。另外由于要从ProxyFactoryBean获得代理对象,也会使应用和Spring之间的耦合度增加,并且很多时候可维护性不强(我个人认为耦合这个不是最主要的原因,毕竟现在Spring已成为实际上的规范了)。


Spring中自动创建代理器(分类)

在内部,Spring使用BeanPostProcessor让自动生成代理。基于BeanPostProcessor的自动代理创建器的实现类,将根据一些规则在容器实例化Bean时为匹配的Bean生成代理实例。代理创建器可以分为三类:

  • 基于Bean配置名规则的自动代理生成器:允许为一组特定配置名的Bean自动创建代理实例的代理创建器,实现类为BeanNameAutoProxyCreator
  • 基于Advisor匹配机制的自动代理创建器它会对容器中的所有Advisor进行扫描,自动将这些切面应用到匹配的Bean中,实现类是DefaultAdvisorAutoProxyCreator(它也支持前缀匹配)
  • 基于Bean中AspectJ注解的自动代理生成器:为包含AspectJ注解的切入的Bean自动创建代理实例

前提

首先,单独看AbstractAutoProxyCreator的继承体系,分析可知,我们需要先去了解一下ProxyProcessorSupport干了啥(之前系列文章讲过,这里再重复一次),和SmartInstantiationAwareBeanPostProcessor中相关回调接口的调用时机


在AbstractAutoProxyCreator类中,有这样一个属性,并且该属性很多地方用到了,因此这里还需求先科普一下TargetSourceCreator的作用,但是科普这个之前,我们还需要再来聊聊TargetSource


ProxyProcessorSupport

简单的说它就是提供为代理创建器提供了一些公共方法实现:

具有代理处理器通用功能的基类,特别是 ClassLoader 管理和 evaluateProxyInterfaces 算法。

@SuppressWarnings("serial")
public class ProxyProcessorSupport extends ProxyConfig implements Ordered, BeanClassLoaderAware, AopInfrastructureBean 

	/**
AOP的自动代理创建器必须在所有的别的processors之后执行,以确保它可以代理到所有的小伙伴们,即使需要双重代理得那种
	 */
	private int order = Ordered.LOWEST_PRECEDENCE;
    
    //代理类的类加载器
	@Nullable
	private ClassLoader proxyClassLoader = ClassUtils.getDefaultClassLoader();
    
    //代理类的类加载器是否被手动配置了---即用户是否手动指定了类加载器
	private boolean classLoaderConfigured = false;

	public void setOrder(int order) 
		this.order = order;
	

	@Override
	public int getOrder() 
		return this.order;
	

	/**
手动设置代理类加载器
	 */
	public void setProxyClassLoader(@Nullable ClassLoader classLoader) 
		this.proxyClassLoader = classLoader;
		//如果不为空,说明手动设置生效,打个标记
		this.classLoaderConfigured = (classLoader != null);
	
	
	@Nullable
	protected ClassLoader getProxyClassLoader() 
		return this.proxyClassLoader;
	
//因为继承了BeanClassLoaderAware,因此默认的代理类加载器就是beanFactory用来加载所有bean的beanClassLoader
	@Override
	public void setBeanClassLoader(ClassLoader classLoader) 
	//手动配置的优先级更高,无法覆盖
		if (!this.classLoaderConfigured) 
			this.proxyClassLoader = classLoader;
		
	


	/**
	 * 检查给定类上的所有接口,然后检查分析决定代理方式
	 */
	protected void evaluateProxyInterfaces(Class<?> beanClass, ProxyFactory proxyFactory) 
	//拿到目标类上的所有接口
		Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, getProxyClassLoader());
		//是否存在合理的接口---可以决定是否采用jdk动态代理,如果为false则走cglib动态代理
		boolean hasReasonableProxyInterface = false;
		for (Class<?> ifc : targetInterfaces) 
			if (
              //pass内部的回调接口
              !isConfigurationCallbackInterface(ifc) && 
               //pass内部语言接口
               !isInternalLanguageInterface(ifc) &&
					//当前接口内是否存在方法
					ifc.getMethods().length > 0) 
				hasReasonableProxyInterface = true;
				break;
			
		
		//如果存在合理的接口
		if (hasReasonableProxyInterface) 
			// Must allow for introductions; can't just set interfaces to the target's interfaces only.
			// 这里Spring的Doc特别强调了:不能值只把合理的接口设置进去,而是都得加入进去
			for (Class<?> ifc : targetInterfaces) 
			//存在合理的接口,说明当前会采用jdk代理,并且代理类需要实现目标对象实现的所有接口
				proxyFactory.addInterface(ifc);
			
		
		else 
		// 这个很明显设置true,表示使用CGLIB得方式去创建代理了~~~~
		//proxyFactory继承了proxyConfig,这里调用的是proxyConfig的setProxyTargetClass方法
			proxyFactory.setProxyTargetClass(true);
		
	

	/**
判断此接口类型是否属于:容器去回调的类型,这里例举处理一些接口 初始化、销毁、自动刷新、自动关闭、Aware感知等等
	 */
	protected boolean isConfigurationCallbackInterface(Class<?> ifc) 
		return (InitializingBean.class == ifc || DisposableBean.class == ifc || Closeable.class == ifc ||
				AutoCloseable.class == ifc || ObjectUtils.containsElement(ifc.getInterfaces(), Aware.class));
	

	/**
	是否是如下通用的接口。若实现的是这些接口也会排除,不认为它是实现了接口的类
	 */
	protected boolean isInternalLanguageInterface(Class<?> ifc) 
		return (ifc.getName().equals("groovy.lang.GroovyObject") ||
				ifc.getName().endsWith(".cglib.proxy.Factory") ||
				ifc.getName().endsWith(".bytebuddy.MockAccess"));
	




该类最重要的就是evaluateProxyInterfaces方法,来评估是该采用jdk还是cglib动态代理,该方法决定采用哪种代理方式后,会直接设置ProxyFactory的相关属性


SmartInstantiationAwareBeanPostProcessor

AbstractAutoProxyCreator是对自动代理创建器的一个抽象实现。最重要的是,它实现了SmartInstantiationAwareBeanPostProcessor接口,因此会介入到Spring IoC容器Bean实例化的过程,因此由此为入口进行展开~

Initialization是初始化的意思,意味着该bean后置处理器接口中的两个方法会在bean的初始化前后被调用,这里初始化指的是bean的初始化方法被调用的前后,例如:init-method等


爷爷BeanPostProcessor

public interface BeanPostProcessor 
	@Nullable
	default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException 
		return bean;
	

	@Nullable
	default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException 
		return bean;
	



该后置处理器中的两个方法被调用的源码时机如下:

AbstractAutowireCapableBeanFactory

	protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) 
		if (System.getSecurityManager() != null) 
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> 
				invokeAwareMethods(beanName, bean);
				return null;
			, getAccessControlContext());
		
		else 
			invokeAwareMethods(beanName, bean);
		

		Object wrappedBean = bean;
		if (mbd == null || !mbd.isSynthetic()) 
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		

		try 
			invokeInitMethods(beanName, wrappedBean, mbd);
		
		catch (Throwable ex) 
			throw new BeanCreationException(
					(mbd != null ? mbd.getResourceDescription() : null),
					beanName, "Invocation of init method failed", ex);
		
		if (mbd == null || !mbd.isSynthetic()) 
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		

		return wrappedBean;
	

initializeBean会在doCreateBean方法中被调用,我保留了该方法主要骨干,大家可以回顾一下,如果想要了解完整流程,可以去看我之前写的初始化流程源码分析:

AbstractAutowireCapableBeanFactory

	protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException 
...
			instanceWrapper = createBeanInstance(beanName, mbd, args);
...

			applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
...

		// Eagerly cache singletons to be able to resolve circular references
		// even when triggered by lifecycle interfaces like BeanFactoryAware.
		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
				isSingletonCurrentlyInCreation(beanName));
				
		if (earlySingletonExposure) 
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
			

		// Initialize the bean instance.
		    Object exposedObject = bean;
			populateBean(beanName, mbd, instanceWrapper);
			exposedObject = initializeBean(beanName, exposedObject, mbd);
 ...
		// Register bean as disposable.
			registerDisposableBeanIfNecessary(beanName, bean, mbd);
..
		return exposedObject;
	

爸爸InstantiationAwareBeanPostProcessor

Instantiation是实例化的意思,意味着该bean后置处理器相关方法会在bean的实例化前后被调用,这里实例化的意思是bean被创建出来的前后,也就是反射创建实例的前后,注意和上面的初始化过程进行区分

public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor 
	@Nullable
	default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException 
		return null;
	
   
	default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException 
		return true;
	

	@Nullable
	default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)
			throws BeansException 

		return null;
	

	@Deprecated
	@Nullable
	default PropertyValues postProcessPropertyValues(
			PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException 

		return pvs;
	


可以看出该后置处理器在爷爷上面增加了四个回调接口,这四个回调接口又可以细分为实例化前后和属性处理接口,那么我们先分析实例化接口何时被调用


AbstractAutowireCapableBeanFactory

doGetBean中,如果缓存没有的话,会按照bean的scope来获取bean,但是无论是啥子scope,最终都是通过createBean来创建bean实例然后返回的

同上,这里只列出重要的部分,其余全部删除,完整版,可以参考之前我写的初始化源码流程分析。

	protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException 
			...
		RootBeanDefinition mbdToUse = mbd;
		...
			// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
			//这里如果返回的bean不为空,会直接返回,形成短路
			//后面初始化啥子流程,压根不走,因此我们可以在这里通过bean定义创建,然后返回代理对象
			Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
			if (bean != null) 
				return bean;
			
          ...

		//反射创建bean实例
			Object beanInstance = doCreateBean(beanName, mbdToUse, args);
			...
			return beanInstance;
...

大家是不是很奇怪,postProcessAfterInstantiation方法怎么没在doCreateBean方法下面出现呢?

那是因为他放到了populateBean方法里面,并且剩余的两个关于属性的回调接口,也是在这里被调用的,下面我们就一并分析一波:

	protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException 
...
		// Initialize the bean instance.
		    Object exposedObject = bean;
		    //populateBean是我们需要重点看的
			populateBean(beanName, mbd, instanceWrapper);
			exposedObject = initializeBean(beanName, exposedObject, mbd);
 ...
	

正式分析:

postProcessAfterInstantiation返回值是boolean,这点注意一下

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) 
		...
		// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
		// state of the bean before properties are set. This can be used, for example,
		// to support styles of field injection.
		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) 
			for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) 
			//postProcessAfterInstantiation的返回值,觉得是否跳过对当前bean的属性赋值过程,如果返回false,表示跳过
				if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) 
					return;
				
			
		

		PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
        ....
           
		boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
		boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);

		PropertyDescriptor[] filteredPds = null;
		if (hasInstAwareBpps) 
			if (pvs == null) 
				pvs = mbd.getPropertyValues();
			
			for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) 
			//postProcessProperties
				PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
				if (pvsToUse == null) 
					if (filteredPds == null) 
					//filterPropertyDescriptorsForDependencyCheck就是返回当前beanWrapper里面PropertyValues对应的属性描述符集合,只做了一件事,就是会将那些被排除掉,不需要注入的接口,例如:aware接口等,从描述符集合中移除,然后返回
						filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
					
					//postProcessPropertyValues
					pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
					if (pvsToUse == null) 
						return;
					
				
				pvs = pvsToUse;
			
		
...
		if (pvs != null) 
		//属性正式赋值操作
			applyPropertyValues(beanName, mbd, bw, pvs);
		
	


还有fresh方法中的preareFactory中也设置了一些依赖忽略的属性,就是如果你在你的类中某处需要注入这些被忽略的接口,那么spring是不会帮你进行自动注入的


儿子SmartInstantiationAwareBeanPostProcessor

public interface SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor 
//预测最终从该处理器的 postProcessBeforeInstantiation 回调返回的 bean 的类型。
//因为上面讲过,如果postProcessBeforeInstantiation返回值非null的话,那么就直接短路了
	@Nullable
	default Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException 
		return null;
	

//确定用于给定 bean 的候选构造函数。
//createBeanInstance方法内部会尝试通过后置处理器来决定给定bean的构造函数
	@Nullable
	default Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName)
			throws BeansException 

		return null;
	

//获取对指定 bean 的早期访问的引用,通常用于解析循环引用。
//
	default Object getEarlyBeanReference(Object bean, String beanName) throws BeansException 
		return bean;
	



determineCandidateConstructors调用时机:

	protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) 
Spring读源码系列之AOP--04---proxyFactory创建代理对象

Spring读源码系列之AOP--02---aop基本概念扫盲---下

Spring读源码系列之AOP--03---aop底层基础类学习

Spring读源码系列之AOP--08--aop执行完整源码流程之自动代理创建器导入的两种方式

Spring读源码系列之AOP--05---aop常用工具类学习

Spring读源码系列之AOP--06---AopProxy===>spring使用jdk和cglib生成代理对象的终极奥义