关于后端:Spring源码解析之八finishBeanFactoryInitialization方法即初始化单例bean

53次阅读

共计 27930 个字符,预计需要花费 70 分钟才能阅读完成。

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 初始化后做一些事,咱们写一个简略的实例测试一下。

其余中央读者看正文理解一下即可,咱们开始持续深刻 getBean() 办法。

getBean() 办法外部调用了 doGetBean() 咱们间接看 doGetBean 办法。

    
    // 咱们在分析初始化 Bean 的过程,然而 getBean 办法咱们常常是用来从容器中获取 Bean 用的,留神切换思路,// 曾经初始化过了就从容器中间接返回,否则就先初始化再返回
    protected <T> T doGetBean(String name, @Nullable Class<T> 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 定义中的 <lookup-method />
        // 和 <replaced-method />,如果读者感兴趣,回到 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。如下图:

doCreateBean 办法有三个外围流程。

(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<?> constructorToUse;
            synchronized (bd.constructorArgumentLock) {constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
                if (constructorToUse == null) {final Class<?> clazz = bd.getBeanClass();
                    if (clazz.isInterface()) {throw new BeanInstantiationException(clazz, "Specified class is an interface");
                    }
                    try {if (System.getSecurityManager() != null) {
                            constructorToUse = AccessController.doPrivileged((PrivilegedExceptionAction<Constructor<?>>) 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 等注解,这些注解是怎么起作用的呢?

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

正文完
 0