Spring源码解析之八finishBeanFactoryInitialization方法即初始化单例bean

虚幻大学 xuhss 397℃ 0评论

Python微信订餐小程序课程视频

https://edu.csdn.net/course/detail/36074

Python实战量化交易理财系统

https://edu.csdn.net/course/detail/35475
Spring源码解析之八finishBeanFactoryInitialization方法即初始化单例bean

七千字长文深刻解读,Spirng中是如何初始化单例bean的,和面试中最常问的Spring是如何解决循环依赖?

今天解读Spring核心方法refresh()中最最重要的一个方法finishBeanFactoryInitialization()方法,该方法负责初始化所有的单例bean。

finishBeanFactoryInitialization()方法位于refresh()中下标为8的位置。

到目前为止,应该说 BeanFactory 已经创建完成,并且所有的实现了 BeanFactoryPostProcessor 接口的 Bean 都已经初始化并且其中的 postProcessBeanFactory(factory) 方法已经得到回调执行了。而且 Spring 已经“手动”注册了一些特殊的 Bean,如 environmentsystemProperties 等。

剩下的就是初始化 singleton beans 了,大都数我们的业务中都是单例bean,就像我们写的@Controller、@Service的类(没有设置懒加载的)都是在这个地方初始化,以供我们使用,如果没有设置懒加载,那么 Spring 会在接下来初始化所有的 singleton beans。

我们先看一下refresh()的源码,大概看下finishBeanFactoryInitialization(beanFactory)所处的位置。

@Override
    public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            // Prepare this context for refreshing.
            //1、刷新前的准备
            prepareRefresh();

            // Tell the subclass to refresh the internal bean factory.
            //2、将会初始化 BeanFactory、加载 Bean、注册 Bean
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

            // Prepare the bean factory for use in this context.
            //3、设置 BeanFactory 的类加载器,添加几个 BeanPostProcessor,手动注册几个特殊的 bean
            prepareBeanFactory(beanFactory);

            try {
                //4、模板方法
                // Allows post-processing of the bean factory in context subclasses.
                postProcessBeanFactory(beanFactory);

                // Invoke factory processors registered as beans in the context.
                //执行BeanFactory后置处理器
                invokeBeanFactoryPostProcessors(beanFactory);

                // 5、Register bean processors that intercept bean creation.
                //注册bean后置处理器
                registerBeanPostProcessors(beanFactory);

                // Initialize message source for this context.
                //国际化
                initMessageSource();

                // Initialize event multicaster for this context.
                initApplicationEventMulticaster();

                // Initialize other special beans in specific context subclasses.
                //6、模板方法--springboot实现了这个方法
                onRefresh();

                // Check for listener beans and register them.
                //7、注册监听器
                registerListeners();

                // Instantiate all remaining (non-lazy-init) singletons.
                //8、完成bean工厂的初始化**方法重要**********************************************
                finishBeanFactoryInitialization(beanFactory);

                //9、 Last step: publish corresponding event.
                finishRefresh();
            }

我们深入finishBeanFactoryInitialization(beanFactory)中,里面的调用线路错综复杂,还望读者可以做好心理准备。

/**
 * 负责单例bean的初始化
 * Finish the initialization of this context's bean factory,
 * initializing all remaining singleton beans.
 */
    protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
        // Initialize conversion service for this context.
        //最先初始化名字为 conversionService的类,conversionService类 它用来将前端传过来的参数和后端的 controller 方法上的参数进行绑定的时候用
        //尤其是用于非基础类型的转换
        if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
                beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
            beanFactory.setConversionService(
                    //初始化在getBean()方法中实现
                    beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
        }

        // Register a default embedded value resolver if no bean post-processor
        // (such as a PropertyPlaceholderConfigurer bean) registered any before:
        // at this point, primarily for resolution in annotation attribute values.
        if (!beanFactory.hasEmbeddedValueResolver()) {
            beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
        }

        // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
        // 先初始化 LoadTimeWeaverAware 类型的 Bean aop相关注:大概有个印象,以后解析aop会和它串起来。
        String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
        for (String weaverAwareName : weaverAwareNames) {
            getBean(weaverAwareName);
        }

        // Stop using the temporary ClassLoader for type matching.
        beanFactory.setTempClassLoader(null);

        // Allow for caching all bean definition metadata, not expecting further changes.
        //freeze的单词意思是冻结,这个时候已经开始预初始化, bean 定义解析、加载、注册先停止
        beanFactory.freezeConfiguration();

        // Instantiate all remaining (non-lazy-init) singletons.
        //开始初始化
        beanFactory.preInstantiateSingletons();
    }

该方法是判断bean的一系列是不是属于某个类型的bean,如果是就调用getBean()方法,如果不是,就调用beanFactory.preInstantiateSingletons()进行初始化,我们先把getBean()放一放,重点看一看beanFactory.preInstantiateSingletons()方法。

@Override
    public void preInstantiateSingletons() throws BeansException {
        if (logger.isTraceEnabled()) {
            logger.trace("Pre-instantiating singletons in " + this);
        }

        // Iterate over a copy to allow for init methods which in turn register new bean definitions.
        // While this may not be part of the regular factory bootstrap, it does otherwise work fine.
        // this.beanDefinitionNames 保存了所有的 beanNames

        List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

        // Trigger initialization of all non-lazy singleton beans...
        //// 下面这个循环,触发所有的非懒加载的 singleton beans 的初始化操作
        for (String beanName : beanNames) {
            RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
            // 非抽象、非懒加载的 singletons。如果配置了 'abstract = true',那是不需要初始化的
            if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
                // 处理 FactoryBean (负责初始化工厂的bean)
                if (isFactoryBean(beanName)) {
                    // FactoryBean 的话,在 beanName 前面加上 ‘&’ 符号
                    //此处调用getBean()方法
                    Object bean = getBean(FACTORY\_BEAN\_PREFIX + beanName);
                    if (bean instanceof FactoryBean) {
                        FactoryBean factory = (FactoryBean) bean;
                        // 判断当前 FactoryBean 是否是 SmartFactoryBean 的实现
                        boolean isEagerInit;
                        if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                            isEagerInit = AccessController.doPrivileged(
                                    (PrivilegedAction<Boolean>) ((SmartFactoryBean) factory)::isEagerInit,
                                    getAccessControlContext());
                        }
                        else {
                            isEagerInit = (factory instanceof SmartFactoryBean &&
                                    ((SmartFactoryBean) factory).isEagerInit());
                        }
                        if (isEagerInit) {
                            getBean(beanName);
                        }
                    }
                }
                else {
                    // 对于普通的 Bean,只要调用 getBean(beanName) 这个方法就可以进行初始化了
                    getBean(beanName);
                }
            }
        }

        // Trigger post-initialization callback for all applicable beans...
        // 到这里说明所有的非懒加载的 singleton beans 已经完成了初始化
        // 如果我们定义的 bean 是实现了 SmartInitializingSingleton 接口的,那么在这里得到回调
        //如果你想在单例bean初始化后做一些事 那就实现该接口
        for (String beanName : beanNames) {
            Object singletonInstance = getSingleton(beanName);
            if (singletonInstance instanceof SmartInitializingSingleton) {
                SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
                if (System.getSecurityManager() != null) {
                    AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                        smartSingleton.afterSingletonsInstantiated();
                        return null;
                    }, getAccessControlContext());
                }
                else {
                    smartSingleton.afterSingletonsInstantiated();
                }
            }
        }
    }

preInstantiateSingletons()方法的主要任务是进行初始化的,在初始化前同样是一系列判断,如,是否是懒加载的,是否是一个factorybean(一个特别的bean,负责工厂创建的bean),最后调用getBean()方法。

其中有个插曲是否实现了SmartInitializingSingleton接口,将接口让你可以在bean初始化后做一些事,我们写一个简单的实例测试一下。

f874d08cc5153737368c70bd9d4830f6 - Spring源码解析之八finishBeanFactoryInitialization方法即初始化单例bean

其他地方读者看注释了解一下即可,我们开始继续深入getBean()方法。

getBean()方法内部调用了doGetBean()我们直接看doGetBean方法。


    // 我们在剖析初始化 Bean 的过程,但是 getBean 方法我们经常是用来从容器中获取 Bean 用的,注意切换思路,
    // 已经初始化过了就从容器中直接返回,否则就先初始化再返回
    protected  T doGetBean(
 String name, @Nullable Class requiredType, @Nullable Object[] args, boolean typeCheckOnly)
 throws BeansException {

 // 获取一个 “正统的” beanName,处理两种情况,一个是前面说的 FactoryBean(前面带 ‘&’),
 // 一个是别名问题,因为这个方法是 getBean,获取 Bean 用的,你要是传一个别名进来,是完全可以的
 String beanName = transformedBeanName(name);
 // 返回值
 Object bean;

 // Eagerly check singleton cache for manually registered singletons.
 // 检查下是不是已经创建过了
 Object sharedInstance = getSingleton(beanName);
 // 这里说下 args ,虽然看上去一点不重要。前面我们一路进来的时候都是 getBean(beanName),
 // 所以 args 传参其实是 null 的,但是如果 args 不为空的时候,那么意味着调用方不是希望获取 Bean,而是创建 Bean
 if (sharedInstance != null && args == null) {
 if (logger.isTraceEnabled()) {
 if (isSingletonCurrentlyInCreation(beanName)) {
 logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
 "' that is not fully initialized yet - a consequence of a circular reference");
 }
 else {
 logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
 }
 }
 // 下面这个方法:如果是普通 Bean 的话,直接返回 sharedInstance,
 // 如果是 FactoryBean 的话,返回它创建的那个实例对象
 bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
 }

 else {
 // Fail if we're already creating this bean instance:
 // We're assumably within a circular reference.
 // 创建过了此 beanName 的 prototype 类型的 bean,那么抛异常,
 // 往往是因为陷入了循环引用 哦,原来之前的循环依赖都是在这抛的异常,再有问题就不是无头苍蝇了
 if (isPrototypeCurrentlyInCreation(beanName)) {
 throw new BeanCurrentlyInCreationException(beanName);
 }

 // Check if bean definition exists in this factory.
 // 检查一下这个 BeanDefinition 在容器中是否存在 BeanDefinition既是包含了bean的一系列信息
 BeanFactory parentBeanFactory = getParentBeanFactory();
 if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
 // Not found -> check parent.
 // 如果当前容器不存在这个 BeanDefinition,试试父容器中有没有
 String nameToLookup = originalBeanName(name);
 if (parentBeanFactory instanceof AbstractBeanFactory) {
 return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
 nameToLookup, requiredType, args, typeCheckOnly);
 }
 else if (args != null) {
 // Delegation to parent with explicit args.
 // 返回父容器的查询结果
 return (T) parentBeanFactory.getBean(nameToLookup, args);
 }
 else if (requiredType != null) {
 // No args -> delegate to standard getBean method.
 return parentBeanFactory.getBean(nameToLookup, requiredType);
 }
 else {
 return (T) parentBeanFactory.getBean(nameToLookup);
 }
 }

 if (!typeCheckOnly) {
 // typeCheckOnly 为 false,将当前 beanName 放入一个 alreadyCreated 的 Set 集合中。
 markBeanAsCreated(beanName);
 }

 /*
 * 稍稍总结一下:
 * 到这里的话,要准备创建 Bean 了,对于 singleton 的 Bean 来说,容器中还没创建过此 Bean;
 * 对于 prototype 的 Bean 来说,本来就是要创建一个新的 Bean。
 */
 try {
 RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
 checkMergedBeanDefinition(mbd, beanName, args);

 // Guarantee initialization of beans that the current bean depends on.
 // 先初始化依赖的所有 Bean,这个很好理解。
 // 注意,这里的依赖指的是 depends-on 中定义的依赖
 String[] dependsOn = mbd.getDependsOn();
 if (dependsOn != null) {
 for (String dep : dependsOn) {
 // 检查是不是有循环依赖,这里的循环依赖和我们前面说的循环依赖又不一样
 if (isDependent(beanName, dep)) {
 throw new BeanCreationException(mbd.getResourceDescription(), beanName,
 "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
 }
 // 注册一下依赖关系
 registerDependentBean(dep, beanName);
 try {
 // 先初始化被依赖项
 getBean(dep);
 }
 catch (NoSuchBeanDefinitionException ex) {
 throw new BeanCreationException(mbd.getResourceDescription(), beanName,
 "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
 }
 }
 }

 // Create bean instance.
 // 如果是 singleton scope 的,创建 singleton 的实例
 if (mbd.isSingleton()) {
 sharedInstance = getSingleton(beanName, () -> {
 try {
 // 执行创建 Bean,详情继续深入
 // 第三个参数 args 数组代表创建实例需要的参数,不就是给构造方法用的参数,或者是工厂 Bean 的参数嘛,不过要注意,在我们的初始化阶段,args 是 null。
 // 这回我们要到一个新的类了 AbstractAutowireCapableBeanFactory,看类名,AutowireCapable?类名是不是也说明了点问题了。
 // 主要是为了以下场景,采用 @Autowired 注解注入属性值:
 return createBean(beanName, mbd, args);
 }
 catch (BeansException ex) {
 // Explicitly remove instance from singleton cache: It might have been put there
 // eagerly by the creation process, to allow for circular reference resolution.
 // Also remove any beans that received a temporary reference to the bean.
 destroySingleton(beanName);
 throw ex;
 }
 });
 bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
 }
 // 如果是 prototype scope 的,创建 prototype 的实例
 else if (mbd.isPrototype()) {
 // It's a prototype -> create a new instance.
 Object prototypeInstance = null;
 try {
 beforePrototypeCreation(beanName);
 // 执行创建 Bean
 prototypeInstance = createBean(beanName, mbd, args);
 }
 finally {
 afterPrototypeCreation(beanName);
 }
 bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
 }

 else {
 String scopeName = mbd.getScope();
 if (!StringUtils.hasLength(scopeName)) {
 throw new IllegalStateException("No scope name defined for bean ´" + beanName + "'");
 }
 Scope scope = this.scopes.get(scopeName);
 if (scope == null) {
 throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
 }
 try {
 Object scopedInstance = scope.get(beanName, () -> {
 beforePrototypeCreation(beanName);
 try {
 return createBean(beanName, mbd, args);
 }
 finally {
 afterPrototypeCreation(beanName);
 }
 });
 bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
 }
 catch (IllegalStateException ex) {
 throw new BeanCreationException(beanName,
 "Scope '" + scopeName + "' is not active for the current thread; consider " +
 "defining a scoped proxy for this bean if you intend to refer to it from a singleton",
 ex);
 }
 }
 }
 catch (BeansException ex) {
 cleanupAfterBeanCreationFailure(beanName);
 throw ex;
 }
 }

 // Check if required type matches the type of the actual bean instance.
 // 最后,检查一下类型对不对,不对的话就抛异常,对的话就返回了
 if (requiredType != null && !requiredType.isInstance(bean)) {
 try {
 T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
 if (convertedBean == null) {
 throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
 }
 return convertedBean;
 }
 catch (TypeMismatchException ex) {
 if (logger.isTraceEnabled()) {
 logger.trace("Failed to convert bean '" + name + "' to required type '" +
 ClassUtils.getQualifiedName(requiredType) + "'", ex);
 }
 throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
 }
 }
 return (T) bean;
 }

具体的实例化过程在createBean()方法中,我们继续深入createBean()方法。

@Override
    protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
            throws BeanCreationException {

        if (logger.isTraceEnabled()) {
            logger.trace("Creating instance of bean '" + beanName + "'");
        }
        RootBeanDefinition mbdToUse = mbd;

        // Make sure bean class is actually resolved at this point, and
        // clone the bean definition in case of a dynamically resolved Class
        // which cannot be stored in the shared merged bean definition.
        // 确保 BeanDefinition 中的 Class 被加载
        Class resolvedClass = resolveBeanClass(mbd, beanName);
        if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
            mbdToUse = new RootBeanDefinition(mbd);
            mbdToUse.setBeanClass(resolvedClass);
        }

        // Prepare method overrides.
        // 准备方法覆写,这里又涉及到一个概念:MethodOverrides,它来自于 bean 定义中的 
        // 和 ,如果读者感兴趣,回到 bean 解析的地方看看对这两个标签的解析。
        try {
            mbdToUse.prepareMethodOverrides();
        }
        catch (BeanDefinitionValidationException ex) {
            throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
                    beanName, "Validation of method overrides failed", ex);
        }

        try {
            // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
            // 让 InstantiationAwareBeanPostProcessor 在这一步有机会返回代理,
            // 在 《Spring AOP 源码分析》那篇文章中有解释,这里先跳过
            Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
            if (bean != null) {
                return bean;
            }
        }
        catch (Throwable ex) {
            throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
                    "BeanPostProcessor before instantiation of bean failed", ex);
        }

        try {
            // 重头戏,创建 bean
            Object beanInstance = doCreateBean(beanName, mbdToUse, args);
            if (logger.isTraceEnabled()) {
                logger.trace("Finished creating instance of bean '" + beanName + "'");
            }
            return beanInstance;
        }
        catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
            // A previously detected exception with proper bean creation context already,
            // or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
            throw ex;
        }
        catch (Throwable ex) {
            throw new BeanCreationException(
                    mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
        }
    }

我们继续往里看 doCreateBean 这个方法,这个调用过程是真的深。

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
            throws BeanCreationException {

        // Instantiate the bean.
        BeanWrapper instanceWrapper = null;
        if (mbd.isSingleton()) {
            instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
        }
        if (instanceWrapper == null) {
            // 说明不是 FactoryBean,这里实例化 Bean,这里非常关键,细节之后再说**********
            instanceWrapper = createBeanInstance(beanName, mbd, args);
        }
        Object bean = instanceWrapper.getWrappedInstance();
        Class beanType = instanceWrapper.getWrappedClass();
        if (beanType != NullBean.class) {
            mbd.resolvedTargetType = beanType;
        }

        // Allow post-processors to modify the merged bean definition.
        synchronized (mbd.postProcessingLock) {
            if (!mbd.postProcessed) {
                try {
                    applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
                }
                catch (Throwable ex) {
                    throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                            "Post-processing of merged bean definition failed", ex);
                }
                mbd.postProcessed = true;
            }
        }

        // Eagerly cache singletons to be able to resolve circular references
        // even when triggered by lifecycle interfaces like BeanFactoryAware.
        // 下面这块代码是为了解决循环依赖的问题,这是个重头戏,解决循环依赖问题
        boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
                isSingletonCurrentlyInCreation(beanName));
        if (earlySingletonExposure) {
            if (logger.isTraceEnabled()) {
                logger.trace("Eagerly caching bean '" + beanName +
                        "' to allow for resolving potential circular references");
            }
            addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
        }

        // Initialize the bean instance.
        Object exposedObject = bean;
        try {
            // 这一步也是非常关键的,这一步负责属性装配,因为前面的实例只是实例化了,并没有设值,这里就是设值***************
            populateBean(beanName, mbd, instanceWrapper);
            // 还记得 init-method 吗?还有 InitializingBean 接口?还有 BeanPostProcessor 接口?
            // 这里就是处理 bean 初始化完成后的各种回调**************
            exposedObject = initializeBean(beanName, exposedObject, mbd);
        }
        catch (Throwable ex) {
            if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
                throw (BeanCreationException) ex;
            }
            else {
                throw new BeanCreationException(
                        mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
            }
        }
    // 下面这块代码是为了解决循环依赖的问题,这是个重头戏,解决循环依赖问题 
        if (earlySingletonExposure) {
                //循环依赖的核心方法调用
            Object earlySingletonReference = getSingleton(beanName, false);
            if (earlySingletonReference != null) {
                if (exposedObject == bean) {
                    exposedObject = earlySingletonReference;
                }
                else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
                    String[] dependentBeans = getDependentBeans(beanName);
                    Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
                    for (String dependentBean : dependentBeans) {
                        if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                            actualDependentBeans.add(dependentBean);
                        }
                    }
                    if (!actualDependentBeans.isEmpty()) {
                        throw new BeanCurrentlyInCreationException(beanName,
                                "Bean with name '" + beanName + "' has been injected into other beans [" +
                                StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
                                "] in its raw version as part of a circular reference, but has eventually been " +
                                "wrapped. This means that said other beans do not use the final version of the " +
                                "bean. This is often the result of over-eager type matching - consider using " +
                                "'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
                    }
                }
            }
        }

        // Register bean as disposable.
        try {
            registerDisposableBeanIfNecessary(beanName, bean, mbd);
        }
        catch (BeanDefinitionValidationException ex) {
            throw new BeanCreationException(
                    mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
        }

        return exposedObject;
    }

到这里,我们已经分析完了 doCreateBean 方法,总的来说,我们已经说完了整个初始化流程。

在实例化bean后有一个特别重要的知识点,也是面试中最常问的,Spring怎么解决循环依赖问题?核心代码就在这个方法里面。

循环依赖其实就是循环引用,也就是两个或则两个以上的bean互相持有对方,最终形成闭环。比如A依赖于B,B依赖于C,C又依赖于A。如下图:

7698e80419521a89421257048a7831f2 - Spring源码解析之八finishBeanFactoryInitialization方法即初始化单例bean

doCreateBean 方法有三个核心流程。

349d244aa6fd010fdd29a516c5fa54e4 - Spring源码解析之八finishBeanFactoryInitialization方法即初始化单例bean

(1)createBeanInstance:实例化,其实也就是调用对象的构造方法实例化对象

(2)populateBean:填充属性,这一步主要是多bean的依赖属性进行填充

(3)initializeBean:调用spring xml中的init 方法。

从上面讲述的单例bean初始化步骤我们可以知道,循环依赖主要发生在第一、第二步。也就是构造器循环依赖和field循环依赖。

那么我们要解决循环引用也应该从初始化过程着手,对于单例来说,在Spring容器整个生命周期内,有且只有一个对象,所以很容易想到这个对象应该存在Cache中,Spring为了解决单例的循环依赖问题,使用了三级缓存。

我们看一下getSingleton方法。

该方法还依赖于三个map,这三个map就是三级缓存。

/** Cache of singleton objects: bean name to bean instance. */
//单例对象的cache
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

/** Cache of singleton factories: bean name to ObjectFactory. */
// 单例对象工厂的cache
private final Map<String, ObjectFactory> singletonFactories = new HashMap<>(16);

/** Cache of early singleton objects: bean name to bean instance. */
//提前曝光的单例对象的Cache
private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);
@Nullable
    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        // Quick check for existing instance without full singleton lock
        Object singletonObject = this.singletonObjects.get(beanName);

        //判断当前单例bean是否正在创建中,也就是没有初始化完成(比如A的构造器依赖了B对象所以得先去创建B对象
        // 或则在A的populateBean过程中依赖了B对象,得先去创建B对象,这时的A就是处于创建中的状态。
        if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
            singletonObject = this.earlySingletonObjects.get(beanName);

            // 是否允许从singletonFactories中通过getObject拿到对象
            if (singletonObject == null && allowEarlyReference) {
                synchronized (this.singletonObjects) {
                    // Consistent creation of early reference within full singleton lock
                    singletonObject = this.singletonObjects.get(beanName);
                    if (singletonObject == null) {
                        singletonObject = this.earlySingletonObjects.get(beanName);
                        if (singletonObject == null) {
                            ObjectFactory singletonFactory = this.singletonFactories.get(beanName);
                            if (singletonFactory != null) {
                                singletonObject = singletonFactory.getObject();
                                this.earlySingletonObjects.put(beanName, singletonObject);
                                this.singletonFactories.remove(beanName);
                            }
                        }
                    }
                }
            }
        }
        return singletonObject;
    }

分析getSingleton()的整个过程,Spring首先从一级缓存singletonObjects中获取。如果获取不到,并且对象正在创建中,就再从二级缓存earlySingletonObjects中获取。

如果还是获取不到且允许singletonFactories通过getObject()获取,就从三级缓存singletonFactory.getObject()(三级缓存)获取,如果获取到了则:

this.earlySingletonObjects.put(beanName, singletonObject);
                        this.singletonFactories.remove(beanName);

从singletonFactories中移除,并放入earlySingletonObjects中。其实也就是从三级缓存移动到了二级缓存。

从上面三级缓存的分析,我们可以知道,Spring解决循环依赖的诀窍就在于singletonFactories这个三级cache。

里就是解决循环依赖的关键,这段代码发生在createBeanInstance之后,也就是说单例对象此时已经被创建出来(调用了构造器)。这个对象已经被生产出来了,虽然还不完美(还没有进行初始化的第二步和第三步),但是已经能被人认出来了(根据对象引用能定位到堆中的对象),所以Spring此时将这个对象提前曝光出来让大家认识,让大家使用。

这样做有什么好处呢?

让我们来分析一下“A的某个field或者setter依赖了B的实例对象,同时B的某个field或者setter依赖了A的实例对象”这种循环依赖的情况。

A首先完成了初始化的第一步,并且将自己提前曝光到singletonFactories中,此时进行初始化的第二步,发现自己依赖对象B,此时就尝试去get(B),发现B还没有被create,所以走create流程,B在初始化第一步的时候发现自己依赖了对象A,于是尝试get(A),尝试一级缓存singletonObjects(肯定没有,因为A还没初始化完全),尝试二级缓存earlySingletonObjects(也没有),尝试三级缓存singletonFactories,由于A通过ObjectFactory将自己提前曝光了,所以B能够通过ObjectFactory.getObject拿到A对象(虽然A还没有初始化完全,但是总比没有好呀),B拿到A对象后顺利完成了初始化阶段1、2、3,完全初始化之后将自己放入到一级缓存singletonObjects中。

此时返回A中,A此时能拿到B的对象顺利完成自己的初始化阶段2、3,最终A也完成了初始化,进去了一级缓存singletonObjects中,而且更加幸运的是,由于B拿到了A的对象引用,所以B现在hold住的A对象完成了初始化。

知道了这个原理时候,肯定就知道为啥Spring不能解决“A的构造方法中依赖了B的实例对象,同时B的构造方法中依赖了A的实例对象”这类问题了!因为加入singletonFactories三级缓存的前提是执行了构造器,所以构造器的循环依赖没法解决。

接下来我们挑 doCreateBean 中的三个细节出来说说。一个是创建 Bean 实例的 createBeanInstance 方法,一个是依赖注入的 populateBean 方法,还有就是回调方法 initializeBean。

这三个方法也是极其复杂的,读者有兴趣可以继续的深入进去。

1、 createBeanInstance 方法

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
        // Make sure bean class is actually resolved at this point.
        // 确保已经加载了此 class
        Class beanClass = resolveBeanClass(mbd, beanName);

        // 校验一下这个类的访问权限
        if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                    "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
        }

        Supplier instanceSupplier = mbd.getInstanceSupplier();
        if (instanceSupplier != null) {
            return obtainFromSupplier(instanceSupplier, beanName);
        }

        if (mbd.getFactoryMethodName() != null) {
            // 采用工厂方法实例化,不熟悉这个概念的读者请看附录,注意,不是 FactoryBean
            return instantiateUsingFactoryMethod(beanName, mbd, args);
        }

        // Shortcut when re-creating the same bean...
        // 如果不是第一次创建,比如第二次创建 prototype bean。
        // 这种情况下,我们可以从第一次创建知道,采用无参构造函数,还是构造函数依赖注入 来完成实例化
        boolean resolved = false;
        boolean autowireNecessary = false;
        if (args == null) {
            synchronized (mbd.constructorArgumentLock) {
                if (mbd.resolvedConstructorOrFactoryMethod != null) {
                    resolved = true;
                    autowireNecessary = mbd.constructorArgumentsResolved;
                }
            }
        }
        if (resolved) {
            if (autowireNecessary) {
                // 构造函数依赖注入
                return autowireConstructor(beanName, mbd, null, null);
            }
            else {
                // 无参构造函数
                return instantiateBean(beanName, mbd);
            }
        }

        // Candidate constructors for autowiring?
        // 判断是否采用有参构造函数
        Constructor[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
        if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
                mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
            // 构造函数依赖注入
            return autowireConstructor(beanName, mbd, ctors, args);
        }

        // Preferred constructors for default construction?
        ctors = mbd.getPreferredConstructors();
        if (ctors != null) {
            // 构造函数依赖注入
            return autowireConstructor(beanName, mbd, ctors, null);
        }

        // No special handling: simply use no-arg constructor.
        // 调用无参构造函数
        return instantiateBean(beanName, mbd);
    }

看一下instantiateBean方法是怎么做的。

protected BeanWrapper instantiateBean(String beanName, RootBeanDefinition mbd) {
        try {
            Object beanInstance;
            if (System.getSecurityManager() != null) {
                beanInstance = AccessController.doPrivileged(
                        (PrivilegedAction<Object>) () -> getInstantiationStrategy().instantiate(mbd, beanName, this),
                        getAccessControlContext());
            }
            else {
                // 实例化
                beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this);
            }
            // 包装一下,返回
            BeanWrapper bw = new BeanWrapperImpl(beanInstance);
            initBeanWrapper(bw);
            return bw;
        }
        catch (Throwable ex) {
            throw new BeanCreationException(
                    mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
        }
    }

我们可以看到,关键的地方在于:beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);

里面是具体是实例化过程,我们进去看看。

@Override
    public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
        // Don't override the class with CGLIB if no overrides.
        // 如果不存在方法覆写,那就使用 java 反射进行实例化,否则使用 CGLIB,
        // 方法覆写 请参见附录"方法注入"中对 lookup-method 和 replaced-method 的介绍
        if (!bd.hasMethodOverrides()) {
            Constructor</span> constructorToUse;
 synchronized (bd.constructorArgumentLock) {
 constructorToUse = (Constructor</span>) bd.resolvedConstructorOrFactoryMethod;
 if (constructorToUse == null) {
 final Class</span> clazz = bd.getBeanClass();
 if (clazz.isInterface()) {
 throw new BeanInstantiationException(clazz, "Specified class is an interface");
 }
 try {
 if (System.getSecurityManager() != null) {
 constructorToUse = AccessController.doPrivileged(
 (PrivilegedExceptionAction</span>>) clazz::getDeclaredConstructor);
 }
 else {
 constructorToUse = clazz.getDeclaredConstructor();
 }
 bd.resolvedConstructorOrFactoryMethod = constructorToUse;
 }
 catch (Throwable ex) {
 throw new BeanInstantiationException(clazz, "No default constructor found", ex);
 }
 }
 }
 // 利用构造方法进行实例化
 return BeanUtils.instantiateClass(constructorToUse);
 }
 else {
 // Must generate CGLIB subclass.
 // 存在方法覆写,利用 CGLIB 来完成实例化,需要依赖于 CGLIB 生成子类,这里就不展开了。
 // tips: 因为如果不使用 CGLIB 的话,存在 override 的情况 JDK 并没有提供相应的实例化支持
 return instantiateWithMethodInjection(bd, beanName, owner);
 }
 }

到这里,我们就算实例化完成了。我们开始说怎么进行属性注入。

2、populateBean 方法

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
        if (bw == null) {
            if (mbd.hasPropertyValues()) {
                throw new BeanCreationException(
                        mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
            }
            else {
                // Skip property population phase for null instance.
                return;
            }
        }

        // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
        // state of the bean before properties are set. This can be used, for example,
        // to support styles of field injection.
        if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
            for (BeanPostProcessor bp : getBeanPostProcessors()) {
                if (bp instanceof InstantiationAwareBeanPostProcessor) {
                    InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                    if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                        return;
                    }
                }
            }
        }

        // bean 实例的所有属性都在这里了
        PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);

        int resolvedAutowireMode = mbd.getResolvedAutowireMode();
        // 通过名字找到所有属性值,如果是 bean 依赖,先初始化依赖的 bean。记录依赖关系
        if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
            MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
            // Add property values based on autowire by name if applicable.
            if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
                autowireByName(beanName, mbd, bw, newPvs);
            }
            // Add property values based on autowire by type if applicable.
            if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
                autowireByType(beanName, mbd, bw, newPvs);
            }
            pvs = newPvs;
        }

        boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
        boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);

        PropertyDescriptor[] filteredPds = null;
        if (hasInstAwareBpps) {
            if (pvs == null) {
                pvs = mbd.getPropertyValues();
            }
            for (BeanPostProcessor bp : getBeanPostProcessors()) {
                if (bp instanceof InstantiationAwareBeanPostProcessor) {
                    InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                    PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
                    if (pvsToUse == null) {
                        if (filteredPds == null) {
                            filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
                        }
                        // 这里有个非常有用的 BeanPostProcessor 进到这里: AutowiredAnnotationBeanPostProcessor
                        // 对采用 @Autowired、@Value 注解的依赖进行设值,这里的内容也是非常丰富的
                        pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
                        if (pvsToUse == null) {
                            return;
                        }
                    }
                    pvs = pvsToUse;
                }
            }
        }
        if (needsDepCheck) {
            if (filteredPds == null) {
                filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
            }
            checkDependencies(beanName, mbd, filteredPds, pvs);
        }

        if (pvs != null) {
            // 设置 bean 实例的属性值
            applyPropertyValues(beanName, mbd, bw, pvs);
        }
    }

属性注入完成后,这一步其实就是处理各种回调了,这块代码比较简单。

3、 initializeBean方法

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
        if (System.getSecurityManager() != null) {
            AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                invokeAwareMethods(beanName, bean);
                return null;
            }, getAccessControlContext());
        }
        else {
            // 如果 bean 实现了 BeanNameAware、BeanClassLoaderAware 或 BeanFactoryAware 接口,回调
            invokeAwareMethods(beanName, bean);
        }

        Object wrappedBean = bean;
        if (mbd == null || !mbd.isSynthetic()) {
            // BeanPostProcessor 的 postProcessBeforeInitialization 回调
            wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
        }

        try {
            // 处理 bean 中定义的 init-method,
            // 或者如果 bean 实现了 InitializingBean 接口,调用 afterPropertiesSet() 方法
            invokeInitMethods(beanName, wrappedBean, mbd);
        }
        catch (Throwable ex) {
            throw new BeanCreationException(
                    (mbd != null ? mbd.getResourceDescription() : null),
                    beanName, "Invocation of init method failed", ex);
        }
        if (mbd == null || !mbd.isSynthetic()) {
            // BeanPostProcessor 的 postProcessAfterInitialization 回调
            //BeanPostProcessor 的两个回调都发生在这边,只不过中间处理了 init-method
            wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }

        return wrappedBean;
    }

自此,Spring实例化单例非懒加载bean的过程也就完成了,这也是Spirng最最重要的方法了。在我们的日常使用Spring中,定义好各个类,然后在上面加上,@Controller,@Service,Autowired等注解,这些注解是怎么起作用的呢?

想必大部分同学都是知其然,不知其所以然,想必通过本文,读者心中能有一个清楚的认识。

__EOF__

程序员田同学 - 本文链接: https://blog.csdn.net/tianClassmate/p/15984168.html

  • 关于博主: 评论和私信会在第一时间回复。或者直接私信我。
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
  • 声援博主: 如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。

转载请注明:xuhss » Spring源码解析之八finishBeanFactoryInitialization方法即初始化单例bean

喜欢 (0)

您必须 登录 才能发表评论!