(一)Spring IoC源码-2.bean的加载-02从缓存中获取单例bean

xiaoxiao2021-02-28  44

本文已收录于【Spring源码札记专栏】。

关联文章: (一)Spring IoC源码-2.bean的加载-01整体概览 (一)Spring IoC源码-2.bean的加载-02从缓存中获取单例bean (一)Spring IoC源码-2.bean的加载-03从bean实例中获取对象 (一)Spring IoC源码-2.bean的加载-04创建bean

从缓存中获取单例bean是通过DefaultSingletonBeanRegistry.getSingleton(String)实现的。

@Override public Object getSingleton(String beanName) { return getSingleton(beanName, true); } @Nullable protected Object getSingleton(String beanName, boolean allowEarlyReference) { //首先从singletonObjects中获取 Object singletonObject = this.singletonObjects.get(beanName); //如果没有获取到,且bean正在创建过程中(isSingletonCurrentlyInCreation()为true),则尝试从singletonFactories中获取 if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { synchronized (this.singletonObjects) { singletonObject = this.earlySingletonObjects.get(beanName); if (singletonObject == null && allowEarlyReference) { ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName); if (singletonFactory != null) { singletonObject = singletonFactory.getObject(); this.earlySingletonObjects.put(beanName, singletonObject); this.singletonFactories.remove(beanName); } } } } return (singletonObject != NULL_OBJECT ? singletonObject : null); }

单例bean在同一个Spring容器中只创建一次,获取bean的时候,尝试从缓存加载bean。首先从singletonObjects中获取,如果没有获取到,且bean正在创建过程中(isSingletonCurrentlyInCreation()为true),则尝试从earlySingletonObjects中获取,如果还获取不到,就求助于singletonFactories。因为spring创建单例bean的时候,存在循环依赖的问题。比如创建bean a的时候发现bean a引用了bean b,此时会去创建bean b,但又发现bean b引用了bean c,所以此时会去创建bean c,在创建bean c的过程中发现bean c引用bean a。为了避免循环依赖,Spring采取了一种将正在创建的bean实例提早暴露加入到singletonFactories缓存中,一旦下一个bean创建的时候需要依赖上个bean,则直接使用singletonFactories来获取bean。

/** Cache of singleton objects: bean name --> bean instance */ private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256); /** Cache of singleton factories: bean name --> ObjectFactory */ private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16); /** Cache of early singleton objects: bean name --> bean instance */ private final Map<String, Object> earlySingletonObjects = new HashMap<>(16); /** Set of registered singletons, containing the bean names in registration order */ private final Set<String> registeredSingletons = new LinkedHashSet<>(256);

提前暴露bean实例到缓存的时机是在bean实例创建(调用构造方法)之后,初始化bean实例(属性注入)之前。具体在AbstractAutowireCapableBeanFactory类的protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {...}方法中。在该方法中调用了DefaultSingletonBeanRegistry类的addSingletonFactory方法提前暴露bean实例到缓存。

protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) { Assert.notNull(singletonFactory, "Singleton factory must not be null"); synchronized (this.singletonObjects) { if (!this.singletonObjects.containsKey(beanName)) { this.singletonFactories.put(beanName, singletonFactory); this.earlySingletonObjects.remove(beanName); this.registeredSingletons.add(beanName); } } }
转载请注明原文地址: https://www.6miu.com/read-2624478.html

最新回复(0)