关于spring循环依赖时生成代理对象逻辑的疑惑

当A对象和B对象发生循环依赖时,B对象会在什么时候创建代理对象?

最近几天看spring源码 产生了一个疑惑:当A对象和B对象发生循环依赖,A对象被B对象注入时,会将A对象从三级缓存中取出来并调用其方法,但是A对象的不完整对象创建完成后,B对象也就创建完成了,那么B对象是在什么时候判断是否需要生成代理对象的呢?

结论:在这种情况下,spring不会判断B对象是否需要生成代理对象,如果使用了@EnableAspectJAutoProxy注解,会在BeanPostProcessor的后置处理器里进行处理

###后附spring生命周期及spring三级缓存的流程图###

// 查找缓存取得Bean
Object sharedInstance = getSingleton(beanName);
// 此处初期调用 allowEarlyReference传入值为true
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
	// 从一级缓存中查找当前Bean
	Object singletonObject = this.singletonObjects.get(beanName);
    // 判断当前bean是否正在创建中
	if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
        // 从二级缓存中查找当前Bean
		singletonObject = this.earlySingletonObjects.get(beanName);
		if (singletonObject == null && allowEarlyReference) {
			synchronized (this.singletonObjects) {
				// 加锁再次尝试
				singletonObject = this.singletonObjects.get(beanName);
				if (singletonObject == null) {
					singletonObject = this.earlySingletonObjects.get(beanName);
					if (singletonObject == null) {
                        // 从三级缓存中查找当前Bean
						ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
						if (singletonFactory != null) {
                            // 调用三级缓存lambda表达式中的方法
							singletonObject = singletonFactory.getObject();
                            // 放入二级缓存
							this.earlySingletonObjects.put(beanName, singletonObject);
                            // 从三级缓存中移除
							this.singletonFactories.remove(beanName);
						}
					}
				}
			}
		}
	}
	return singletonObject;
}
// 添加到三级缓存 beanName作为key lambda表达式作为value
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
// 判断是否需要AOP代理
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;
}

带着这个疑惑,我进行了数次debug,最终发现它确实是没有执行该逻辑的

我加上@EnableAspectJAutoProxy注解一次次debug,最终发现B对象的代理对象生成逻辑是在BeanPostProcessor的后置方法applyBeanPostProcessorsAfterInitialization中进行处理的 在这之前B一直都是原始对象

@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
		throws BeansException {
	Object result = existingBean;
    // 获取所有的BeanPostProcessor
	for (BeanPostProcessor processor : getBeanPostProcessors()) {
		Object current = processor.postProcessAfterInitialization(result, beanName);
		if (current == null) {
			return result;
		}
		result = current;
	}
	return result;
}

原来,@EnableAspectJAutoProxy注解中导入了一个类:AspectJAutoProxyRegistrar

它会将AnnotationAwareAspectJAutoProxyCreator注册到 BeanDefinitionRegistry中

 

 因此,spring确实是对B对象没有进行AOP代理对象处理,是由AOP在后置处理器中进行处理的

最后放出最近整理的spring生命周期及spring三级缓存的流程图

spring生命周期流程图

spring三级缓存流程图

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值