08_循环依赖中使用aop以及三级缓存使用

结论:
之前已经说过循环依赖,但在不使用aop代理时是不需要三级缓存的,二级缓存也可以实现。那么这次将通过aop代理对象进行实例间的循环依赖来查看三级缓存的使用。
首先来简单看下有aop代理时对象初始化的流程
在这里插入图片描述

相较于之前不进行aop时,会在B初始化时多一个流程 即“为A创建代理”。
这样做的目的是为什么呢,为什么不在实例化A的时候创建代理缓存起来,然后在B注入属性时使用呢。
原因是spring原本正常是在初始化时AbstractAutoProxyCreator这个后置处理器中进行aop代理对象的生成的。但是由于循环依赖需要把代理对象提前进行代理。所以对于循环依赖时后置处理器不在进行代理对象的生成。如果在实例化A之后就进行代理,这样违背了Spring设计的原则,Spring在设计之初就是通过AnnotationAwareAspectJAutoProxyCreator这个后置处理器来在Bean生命周期的最后一步来完成AOP代理,而不是在实例化后就立马进行AOP代理。
所以在实例化A时,会将A的单例工厂缓存起来。并在B注入属性时判断是否需要代理,如果需要,就创建代理对象作为B的属性进行填充。
源码解析:
主要查看三级缓存存储单例工厂

if (earlySingletonExposure) {
	if (logger.isTraceEnabled()) {
		logger.trace("Eagerly caching bean '" + beanName +
		"' to allow for resolving potential circular references");
	}
	// 循环依赖-添加到三级缓存  后续循环依赖 调用getEarlyBeanReference 方法获取实例
	addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}

查看为B创建属性时根据A的单例工厂获取A的代理实例

	protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
		Object exposedObject = bean;
		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
			for (SmartInstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().smartInstantiationAware) {
				exposedObject = bp.getEarlyBeanReference(exposedObject, beanName);
			}
		}
		return exposedObject;
	}

将A对象放到 earlyProxyReferences 中,说明提前进行了Aop。

	public Object getEarlyBeanReference(Object bean, String beanName) {
		Object cacheKey = getCacheKey(bean.getClass(), beanName);
		//提前aop的bean放到 earlyProxyReferences ,在后置处理器执行时判断 earlyProxyReferences是否存在。
		//存在说明已经aop了,无需再后置处理器中进行aop
		this.earlyProxyReferences.put(cacheKey, bean);
		return wrapIfNecessary(bean, beanName, cacheKey);
	}

查看wrapIfNecessary方法

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
		if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
			return bean;
		}

		// advisedBeans表示已经判断过了的bean,false表示此bean不需要进行Aop
		if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
			return bean;
		}

		// 当前正在创建的Bean不用进行AOP,比如切面Bean
		if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
			this.advisedBeans.put(cacheKey, Boolean.FALSE);
			return bean;
		}

		// Create proxy if we have advice.
		// 判断当前bean是否存在匹配的advice,如果存在则要生成一个代理对象
		// 此处根据类以及类中的方法去匹配到Interceptor(也就是Advice),然后生成代理对象,代理对象在执行的时候,还会根据当前执行的方法去匹配
		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
		if (specificInterceptors != DO_NOT_PROXY) {
			// advisedBeans记录了某个Bean已经进行过AOP了
			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;
	}

从源码看,spring是在B填充属性A时,A的单例工厂进行了A实例的代理对象的生成。完成B的初始化后。再完成A的初始化。
在A的初始化后 AbstractAutoProxyCreator这个后置处理器中就不再进行A的代理,而是直接使用生成好的代理进行返回。
源码:
AbstractAutoProxyCreator的后置处理器方法,判断earlyProxyReferences 是否存在

	public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
		if (bean != null) {
			Object cacheKey = getCacheKey(bean.getClass(), beanName);
			//判断是否已经bean是否已经Aop,
			if (this.earlyProxyReferences.remove(cacheKey) != bean) {
				return wrapIfNecessary(bean, beanName, cacheKey);
			}
		}
		return bean;
	}

由以上源码可知。后置处理器不再进行aop。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值