Spring循环依赖三级缓存是否可以减少为二级缓存?( 二 )
1、不管有没有循环依赖 , 都提前创建好代理对象 , 并将代理对象放入缓存 , 出现循环依赖时 , 其他对象直接就可以取到代理对象并注入 。
2、不提前创建好代理对象 , 在出现循环依赖被其他对象注入时 , 才实时生成代理对象 。 这样在没有循环依赖的情况下 , Bean就可以按着Spring设计原则的步骤来创建 。
Spring选择了第二种方式 , 那怎么做到提前曝光对象而又不生成代理呢?
Spring就是在对象外面包一层ObjectFactory , 提前曝光的是ObjectFactory对象 , 在被注入时才在ObjectFactory.getObject方式内实时生成代理对象 , 并将生成好的代理对象放入到第二级缓存Map earlySingletonObjects 。 addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));:
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactoryimplements AutowireCapableBeanFactory {protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {Object exposedObject = bean;if (!mbd.isSynthetic()exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);}}}return exposedObject;}}
左右滑动查看完整代码
为了防止对象在后面的初始化(init)时重复代理 , 在创建代理时 , earlyProxyReferences缓存会记录已代理的对象 。
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupportimplements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {private final Map
左右滑动查看完整代码四. 注入属性和初始化提前曝光之后:
1、通过populateBean方法注入属性 , 在注入其他Bean对象时 , 会先去缓存里取 , 如果缓存没有 , 就创建该对象并注入 。
2、通过initializeBean方法初始化对象 , 包含创建代理 。
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactoryimplements AutowireCapableBeanFactory {protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)throws BeanCreationException {……// Initialize the bean instance.Object exposedObject = bean;try {populateBean(beanName, mbd, instanceWrapper);exposedObject = initializeBean(beanName, exposedObject, mbd);}catch (Throwable ex) {if (ex instanceof BeanCreationException}else {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);}}……}}// 获取要注入的对象public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {protected Object getSingleton(String beanName, boolean allowEarlyReference) {// 一级缓存Object singletonObject = this.singletonObjects.get(beanName);if (singletonObject == nullif (singletonObject == nullif (singletonFactory != null) {singletonObject = singletonFactory.getObject();this.earlySingletonObjects.put(beanName, singletonObject);this.singletonFactories.remove(beanName);}}}}return singletonObject;}}
左右滑动查看完整代码五. 放入已完成创建的单例缓存在经历了以下步骤之后 , 最终通过addSingleton方法将最终生成的可用的Bean放入到单例缓存里 。
1、
AbstractBeanFactory.doGetBean ->
2、
DefaultSingletonBeanRegistry.getSingleton ->
3、
AbstractAutowireCapableBeanFactory.createBean ->
4、
AbstractAutowireCapableBeanFactory.doCreateBean ->
5、
DefaultSingletonBeanRegistry.addSingleton
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {/** Cache of singleton objects: bean name to bean instance. */private final Map singletonObjects = new ConcurrentHashMap<>(256);/** Cache of singleton factories: bean name to ObjectFactory. */private final Map> singletonFactories = new HashMap<>(16);/** Cache of early singleton objects: bean name to bean instance. */private final Map earlySingletonObjects = new HashMap<>(16);protected void addSingleton(String beanName, Object singletonObject) {synchronized (this.singletonObjects) {this.singletonObjects.put(beanName, singletonObject);this.singletonFactories.remove(beanName);this.earlySingletonObjects.remove(beanName);this.registeredSingletons.add(beanName);}}}
左右滑动查看完整代码
文章插图
- 二级缓存 -
上面第三步《为什么要包装一层ObjectFactory对象?》里讲到有两种选择:
1、不管有没有循环依赖 , 都提前创建好代理对象 , 并将代理对象放入缓存 , 出现循环依赖时 , 其他对象直接就可以取到代理对象并注入 。
- 智能手机|双面小米:猛士回归与“屌丝”依赖
- 驱动|开源之系统:Ubuntu20.04电脑安装无线网卡驱动并解决包依赖关系
- Spring security CSRF 跨域访问限制问题
- Spring Boot搭建的一个在线文件预览系统
- 面试官:问你一个,Spring事务是如何传播的?
- 对Spring MVC接口进行Mock测试
- 湖南“速生人工林”成功验收 打造绿色高效循环产业技术创新链
- Spring Cloud Alibaba之 Sentinel
- SpringBoot+MyBatis+MySQL读写分离实现
- SpringBoot构造流程源码分析:Web应用类型推断