Spring源码之IoC,单例Bean添加到一、二、三级缓存的时机,源码解读

三个缓存都存在于DefaultSingletonBeanRegistry中。以AbstractBeanFactory中的getBean作为入口。

添加到一级缓存的时机

一级缓存主要用于存储单例模式下创建完毕的Bean实例,包括该Bean的实例化,依赖注入,初始化等都完成的一个完整的Bean。

所以添加到一级缓存中的时机:自然是完成Bean的实例化,依赖注入,初始化等操作,生成完整的单例Bean后进行添加的。

源码位置:getBean方法——doGetBean方法——getSingleton创建单例Bean——addSingleton方法

doGetBean方法中创建单例Bean的代码

可以看到,getSingleton方法的入参传入是ObjectFactory类型,使用匿名内部类的方式,传入一个实现了ObjectFactory类的getObject方法的对象,getObject方法通过调用createBean方法完成对象的创建。

                if (mbd.isSingleton()) {
    
    
                    sharedInstance = this.getSingleton(beanName, () -> {
    
    
                        try {
    
    
                            return this.createBean(beanName, mbd, args);
                        } catch (BeansException var5) {
    
    
                            this.destroySingleton(beanName);
                            throw var5;
                        }
                    });
                    beanInstance = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                }

getSingleton(String beanName, ObjectFactory<?> singletonFactory)方法源码

1、该方法使用synchronized对一级缓存进行加锁。
2、获取到锁后从一级缓存中取Bean对象,取到则直接返回
3、缓存中取不到,则调用ObjectFactory的getObject方法创建对象
4、最后调用addSingleton方法,把单例Bean添加到缓存中

    public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
    
    
        Assert.notNull(beanName, "Bean name must not be null");
        synchronized(this.singletonObjects) {
    
    
            Object singletonObject = this.singletonObjects.get(beanName);
            if (singletonObject == null) {
    
    
                if (this.singletonsCurrentlyInDestruction) {
    
    
                    throw new BeanCreationNotAllowedException(beanName, "Singleton bean creation not allowed while singletons of this factory are in destruction (Do not request a bean from a BeanFactory in a destroy method implementation!)");
                }

                if (this.logger.isDebugEnabled()) {
    
    
                    this.logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
                }

                this.beforeSingletonCreation(beanName);
                boolean newSingleton = false;
                boolean recordSuppressedExceptions = this.suppressedExceptions == null;
                if (recordSuppressedExceptions) {
    
    
                    this.suppressedExceptions = new LinkedHashSet();
                }

                try {
    
    
                    singletonObject = singletonFactory.getObject();
                    newSingleton = true;
                } catch (IllegalStateException var16) {
    
    
                    singletonObject = this.singletonObjects.get(beanName);
                    if (singletonObject == null) {
    
    
                        throw var16;
                    }
                } catch (BeanCreationException var17) {
    
    
                    BeanCreationException ex = var17;
                    if (recordSuppressedExceptions) {
    
    
                        Iterator var8 = this.suppressedExceptions.iterator();

                        while(var8.hasNext()) {
    
    
                            Exception suppressedException = (Exception)var8.next();
                            ex.addRelatedCause(suppressedException);
                        }
                    }

                    throw ex;
                } finally {
    
    
                    if (recordSuppressedExceptions) {
    
    
                        this.suppressedExceptions = null;
                    }

                    this.afterSingletonCreation(beanName);
                }

                if (newSingleton) {
    
    
                    this.addSingleton(beanName, singletonObject);
                }
            }

            return singletonObject;
        }
    }

addSingleton方法源码

1、该方法使用synchronized对一级缓存进行加锁。获取singletonObjects锁
2、调用put方法添加到一级缓存
3、清理三级缓存singletonFactories中的该Bean
4、清理二级缓存earlySingletonObjects中的该Bean
5、把该Bean添加到成功列表中,registeredSingletons记录已经创建成功的单例名称。

    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);
        }
    }

添加到二级缓存的时机

源码位置:getBean方法——doGetBean方法——getSingleton方法

doGetBean中首次调用getSingleton

getSingleton(beanName)此方法先从一级和二级缓存中取,如果都取不到,允许从三级缓存中取,如果从三级缓存中取到Bean。

如果从三级缓存中取到对应的Bean,则把Bean添加到二级缓存,并在三级缓存中清除

    protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
    
    
        String beanName = this.transformedBeanName(name);
        Object sharedInstance = this.getSingleton(beanName);
    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    
    
        Object singletonObject = this.singletonObjects.get(beanName);
        if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) {
    
    
            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) {
    
    
                            ObjectFactory<?> singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName);
                            if (singletonFactory != null) {
    
    
                                singletonObject = singletonFactory.getObject();
                                // 添加到二级缓存
                                this.earlySingletonObjects.put(beanName, singletonObject);
                                // 在三级缓存中清除
                                this.singletonFactories.remove(beanName);
                            }
                        }
                    }
                }
            }
        }

        return singletonObject;
    }

添加到三级缓存的时机

调用createBeanInstance进行Bean实例化之后,调用populateBean进行依赖注入之前

源码位置:getBean方法——doGetBean方法——addSingletonFactory方法

doGetBean方法调用addSingletonFactory方法的源码

        boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName);
        if (earlySingletonExposure) {
    
    
            if (this.logger.isTraceEnabled()) {
    
    
                this.logger.trace("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references");
            }

            this.addSingletonFactory(beanName, () -> {
    
    
                return this.getEarlyBeanReference(beanName, mbd, bean);
            });
        }

addSingletonFactory方法源码

1、获取锁
2、添加到三级缓存
3、从二级缓存中进行清理
4、把该Bean添加到成功列表中,registeredSingletons记录已经创建成功的单例名称。

    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);
            }

        }
    }

总结

添加到一级缓存:完成Bean的实例化,依赖注入,初始化等操作,生成完整的单例Bean后进行添加。

添加到二级缓存:通过getBean获取实例,在三级缓存中获取到时,添加到二级缓存,并清理三级缓存。

添加到三级缓存:通过createBeanInstance实例化Bean之后,调用populateBean进行依赖注入之前。

猜你喜欢

转载自blog.csdn.net/weixin_43073775/article/details/117903947