【源码】Spring AOP 12 原理解读一

前言

这章节开始,基于之前的学习,我会结合部分源码了解一下 Spring AOP 是如何实现的

ProxyConfig

public class ProxyConfig implements Serializable {

	// 是否代理目标类,决定代理方式
	private boolean proxyTargetClass = false;

	// 是否进行优化,默认 false,如果 exposeProxy 设置为 true,该属性的 true 也将不起作用
	private boolean optimize = false;

	// 是否允许代理对象强转为 Advised 对象,默认 false
	boolean opaque = false;

	// 是否将代理对象暴露至 AopContext
	boolean exposeProxy = false;

	// 是否冻结配置信息
	private boolean frozen = false;

}

代理配置信息基类,这些属性主要是干涉或决定最终的代理方式,具体可参考 DefaultAopProxyFactory#createAopProxy 方法,之前也了解过

ProxyProcessorSupport

public class ProxyProcessorSupport extends ProxyConfig implements Ordered, BeanClassLoaderAware, AopInfrastructureBean {

	// ...

	protected void evaluateProxyInterfaces(Class<?> beanClass, ProxyFactory proxyFactory) {
		
		// 获取指定 bean 的所有接口
		Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, getProxyClassLoader());
		boolean hasReasonableProxyInterface = false;

		/**
		 * 只要目标接口:
		 * 1)非 InitializingBean DisposableBean Closeable AutoCloseable Aware族 
		 * & 2)不是一些指定接口比如 groovy.lang.GroovyObject
		 * & 3)不是空方法
		 * 这里就会标记 hasReasonableProxyInterface,这意味着会被添加为代理接口
		 * 		否则会标记 proxyFactory.setProxyTargetClass(true)
		 * 这影响到最终使用哪种代理方式	
		 */
		for (Class<?> ifc : targetInterfaces) {
			if (!isConfigurationCallbackInterface(ifc) && !isInternalLanguageInterface(ifc) &&
					ifc.getMethods().length > 0) {
				hasReasonableProxyInterface = true;
				break;
			}
		}
		if (hasReasonableProxyInterface) {
			for (Class<?> ifc : targetInterfaces) {
				proxyFactory.addInterface(ifc);
			}
		}
		else {
			proxyFactory.setProxyTargetClass(true);
		}
	}

	// ...

}

ProxyProcessorSupport

这是一个后处理阶段代理的基类:

  • 提供了 evaluateProxyInterfaces 方法,主要用于推断目标类的接口,往本质了说就是觉得最终使用哪种代理方式
  • 它有两个核心的分支:
    • AbstractAdvisingBeanPostProcessor,该分支主要是提供一个指定的 Advisor,作为一个 BeanPostProcessor 在合适的后处理阶段创建对应的代理对象
    • AbstractAutoProxyCreator,本文要了解的重点,也是 Spring AOP 的关键类

AbstractAutoProxyCreator

这个类的内容稍微有点多,为了方便阅读分成几个部分了解

1
	// 从 proxyTypes 中获取
	// 在代理对象创建后根据类型记录到 proxyTypes 中
	@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;
	}

	/**
	 * 提前暴露的的代理过的实例
	 * 如果一个 bean 被循环依赖了,那这个地方可能就提前给它创建
	 * 		代理对象了,就记录到 earlyProxyReferences 中
	 */
	@Override
	public Object getEarlyBeanReference(Object bean, String beanName) {
		Object cacheKey = getCacheKey(bean.getClass(), beanName);
		this.earlyProxyReferences.put(cacheKey, bean);
		return wrapIfNecessary(bean, beanName, cacheKey);
	}

	/**
	 * 在 postProcessBeforeInstantiation 阶段
	 * 如果发现有自定义的 TargetSourceCreator[] customTargetSourceCreators 属性,
	 * 		则会基于此获取 TargetSource 对象,然后代理返回
	 * 如果在此处被代理,就记录到 targetSourcedBeans 中
	 * 从 Spring 生命周期来看,如果此处返回一个非空实例,则生命周期被短路,直接执行
	 * 		postProcessAfterInitialization 阶段
	 */
	@Override
	public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
	
		// ...
		
	}

	// 属性不做处理
	@Override
	public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
		return pvs;
	}

	/**
	 * 大多数情况下,代理过程是在这个阶段发生的
	 */
	@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;
	}

首先,AbstractAutoProxyCreator 是一个 SmartInstantiationAwareBeanPostProcessor,这意味着它会参与 bean 的生命周期,在适当的阶段干涉 bean,作为一个 SmartInstantiationAwareBeanPostProcessor,结合以上代码,它参与的生命周期各阶段行为有:

  1. predictBeanType:该方法主要用于获取 bean 的类型,此处是基于一个缓存属性 proxyTypes,那它的插入时机必然就是代理对象创建后,代理对象的创建时机可以继续往下看
  2. postProcessBeforeInstantiation:这是第一处可能创建代理对象的方法,当我们指定了 TargetSourceCreator[] customTargetSourceCreators 属性时,此处会基于此获取 TargetSource 然后创建代理对象,同时被记入 targetSourcedBeans 属性。另外从 bean 的生命周期角度来说,此处如果创建代理对象,则生命周期被短路至 postProcessAfterInitialization
  3. determineCandidateConstructors:推断构造方法,此处无动作
  4. getEarlyBeanReference:提前暴露实例,这个方法主要是用来解决循环依赖的,作用是提前暴露一个实例,而此处自然就是暴露代理过的实例,所以这是第二处可能创建代理对象的地方,这地方代理过的 bean 被记入 earlyProxyReferences 属性
  5. postProcessAfterInstantiation:无动作
  6. postProcessProperties:无动作
  7. postProcessBeforeInitialization:无动作
  8. postProcessAfterInitialization:大多数 bean 发生代理是在这个阶段,代理方法为 wrapIfNecessary

关于 SmartInstantiationAwareBeanPostProcessor 如果有疑问,可以了解该文章:

Spring —— BeanPostProcessor 后处理器梳理

2
	protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {

		// 在 targetSourcedBeans 阶段被创建过代理
		if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
			return bean;
		}
		// 在 targetSourcedBeans 阶段校验不需要生成代理
		if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
			return bean;
		}
		
		/**
		 * isInfrastructureClass: 是否 AOP 组件类,比如 Advice Pointcut Advisor
		 * 		或者实现了 AopInfrastructureBean
		 * shouldSkip:子类可以拓展,此处主要是跳过后缀 .ORIGINAL 的 beanName
		 */
		if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
			this.advisedBeans.put(cacheKey, Boolean.FALSE);
			return bean;
		}

		/**
		 * 此类暴露的核心抽象方法:getAdvicesAndAdvisorsForBean,有子类实现
		 * 主要是获取当前 bean 对应的 Interceptors Chain
		 */
		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;
		}

		// 子类判断该 bean 不需要代理,比如没有适合它的 Interceptor
		this.advisedBeans.put(cacheKey, Boolean.FALSE);
		return bean;
	}
  • 做了一些前置处理,代理过或者之前推断过不需要代理的就不继续了
  • 如果是代理基础组件或者基于 shouldSkip 方法判断不需要代理,也就不继续了,子类可以复写 shouldSkip 方法
  • 接下来就准备开始代理了,在这之前,我们要获取当前 bean 上的所有拦截器,因此此处暴露了一个主要的抽象方法 getAdvicesAndAdvisorsForBean 供子类实现,主要用于返回符合当前 bean 的所有 Interceptors
  • 如果子类返回 DO_NOT_PROXY 那就不代理了,否则就开始创建,对应方法 createProxy
3
	protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
			@Nullable Object[] specificInterceptors, TargetSource targetSource) {

		// ...

		ProxyFactory proxyFactory = new ProxyFactory();
		proxyFactory.copyFrom(this);

		// ...

		/**
		 * 基于获取的 Interceptors 构建 Advisors 用于 proxyFactory
		 * 这里主要是把用户指定的 interceptorNames 也加进来,通常没有,当然最后
		 * 		也要基于 DefaultAdvisorAdapterRegistry#wrap 包装成 Advisor
		 */
		Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
		proxyFactory.addAdvisors(advisors);
		proxyFactory.setTargetSource(targetSource);

		// 子类定制
		customizeProxyFactory(proxyFactory);

		// ...

		// 创建代理
		return proxyFactory.getProxy(classLoader);
	}

简化了一下代码,可以看到:

  • Spring AOP 创建代理用的 AdvisedProxyFactory,之前了解过的
  • 处理一些 ProxyFactory 的属性后,把之前针对这个 bean 获取的 Interceptors 包装成 Advisors 返回,另外这里也会把指定的 interceptorNames 属性的 Interceptors 也加进来,作为通用拦截器,不过一般情况下没有
  • Interceptors 包装成 Advisors 由 DefaultAdvisorAdapterRegistry#wrap 方法完成,之前了解过的
4
	@Nullable
	protected abstract Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName,
			@Nullable TargetSource customTargetSource) throws BeansException;

至此,整个代理的基调已经定下来了,具体代不代理目标 bean、赋予什么行为,则是由子类实现的 getAdvicesAndAdvisorsForBean 方法决定的

序列图

AbstractAutoProxyCreator

总结

在本章节代理的基调了解的差不多了,笼统的概括:
在每个 bean 合适的生命周期阶段为其创建代理对象,但具体是哪些 bean、赋予那些行为,则由子类决定

上一篇:【源码】Spring AOP 11 AopProxyFactory AopProxy

下一篇:【源码】Spring AOP 13 原理解读二

参考

【小家Spring】Spring AOP的核心类:AbstractAdvisorAutoProxy自动代理创建器深度剖析(AnnotationAwareAspectJAutoProxyCreator)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值