优秀的编程知识分享平台

网站首页 > 技术文章 正文

Spring源码阅读之singleton类型bean的初始化流程,可以细品一下

nanyue 2024-09-07 16:43:11 技术文章 9 ℃

Spring源码阅读之初始化"非懒加载bean"实例-3

0. 导读

写在前面的一点 “废话”,关于流程图的一点说明,有读者朋友反馈说之前的文章内容太干了,要是有点图文说明就更好了,经过博主仔细考虑之后,决定以流程图的方式加以适当配合说明,希望朋友们喜欢。(本文来自公众号:z小赵

接着上篇文章,本文接着bean实例的创建过程,主要分为以下4部分

  1. getBean()流程分析
  2. getMergedLocalBeanDefinition()流程分析
  3. doCreateBean()流程分析
  4. getObjectForBeanInstance()流程分析
  5. 循环依赖解决方案剖析1.getBean() 流程总览

2.getBean() 源码分析

protected RootBeanDefinition getMergedBeanDefinition(
			String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)
			throws BeanDefinitionStoreException {

    synchronized (this.mergedBeanDefinitions) {
        RootBeanDefinition mbd = null;

        // Check with full lock now in order to enforce the same merged instance.
        // Step1:从mergedBeanDefinitions缓存中获取mbd定义
        if (containingBd == null) {
            mbd = this.mergedBeanDefinitions.get(beanName);
        }

        if (mbd == null) {
            // Step2:如果当前BeanDefinition定义不存在父name
            if (bd.getParentName() == null) {
                // Use copy of given root bean definition.
                // Step2.1:BeanDefinition定义实现了RootBeanDefinition接口,拿当前BeanDefinition克隆一个mbd
                if (bd instanceof RootBeanDefinition) {
                    mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
                }
                else {
                    // Step2.2:拿当前BeanDefinition定义创建一个新的RootBeanDefinition定义。
                    mbd = new RootBeanDefinition(bd);
                }
            }
            else {
                // Child bean definition: needs to be merged with parent.
                BeanDefinition pbd;
                try {
                    // Step3:获取父BeanName
                    String parentBeanName = transformedBeanName(bd.getParentName());
                    // Step3.1:父beanName和当前beanName不相同,使用父beanName创建mbd定义。
                    if (!beanName.equals(parentBeanName)) {
                        pbd = getMergedBeanDefinition(parentBeanName);
                    }
                    else {
                        // Step3.2:使用父BeanFactory创建mbd定义
                        BeanFactory parent = getParentBeanFactory();
                        if (parent instanceof ConfigurableBeanFactory) {
                            pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName);
                        }
                        else {
                            throw new NoSuchBeanDefinitionException(parentBeanName,
                                    "Parent name '" + parentBeanName + "' is equal to bean name '" + beanName +
                                    "': cannot be resolved without an AbstractBeanFactory parent");
                        }
                    }
                }
                catch (NoSuchBeanDefinitionException ex) {
                    throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName,
                            "Could not resolve parent bean definition '" + bd.getParentName() + "'", ex);
                }
                // Deep copy with overridden values.
                // Step3.3:使用父BeanDefinition定义new一个mbd定义,然后在将BeanDefinition定义覆盖到mbd上。
                mbd = new RootBeanDefinition(pbd);
                mbd.overrideFrom(bd);
            }

            // Set default singleton scope, if not configured before.
            // Step4:设置默认scope属性
            if (!StringUtils.hasLength(mbd.getScope())) {
                mbd.setScope(RootBeanDefinition.SCOPE_SINGLETON);
            }

            // A bean contained in a non-singleton bean cannot be a singleton itself.
            // Let's correct this on the fly here, since this might be the result of
            // parent-child merging for the outer bean, in which case the original inner bean
            // definition will not have inherited the merged outer bean's singleton status.
            if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {
                mbd.setScope(containingBd.getScope());
            }

            // Cache the merged bean definition for the time being
            // (it might still get re-merged later on in order to pick up metadata changes)
            // Step5:将创建出来的mbd定义放入mergedBeanDefinitions本地缓存
            if (containingBd == null && isCacheBeanMetadata()) {
                this.mergedBeanDefinitions.put(beanName, mbd);
            }
        }
        // Step6:返回mbd定义
        return mbd;
    }
}

3.getMergedLocalBeanDefinition() 码分析

protected RootBeanDefinition getMergedBeanDefinition(
			String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)
			throws BeanDefinitionStoreException {

    synchronized (this.mergedBeanDefinitions) {
        RootBeanDefinition mbd = null;

        // Check with full lock now in order to enforce the same merged instance.
        // Step1:从mergedBeanDefinitions缓存中获取mbd定义
        if (containingBd == null) {
            mbd = this.mergedBeanDefinitions.get(beanName);
        }

        if (mbd == null) {
            // Step2:如果当前BeanDefinition定义不存在父name
            if (bd.getParentName() == null) {
                // Use copy of given root bean definition.
                // Step2.1:BeanDefinition定义实现了RootBeanDefinition接口,拿当前BeanDefinition克隆一个mbd
                if (bd instanceof RootBeanDefinition) {
                    mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
                }
                else {
                    // Step2.2:拿当前BeanDefinition定义创建一个新的RootBeanDefinition定义。
                    mbd = new RootBeanDefinition(bd);
                }
            }
            else {
                // Child bean definition: needs to be merged with parent.
                BeanDefinition pbd;
                try {
                    // Step3:获取父BeanName
                    String parentBeanName = transformedBeanName(bd.getParentName());
                    // Step3.1:父beanName和当前beanName不相同,使用父beanName创建mbd定义。
                    if (!beanName.equals(parentBeanName)) {
                        pbd = getMergedBeanDefinition(parentBeanName);
                    }
                    else {
                        // Step3.2:使用父BeanFactory创建mbd定义
                        BeanFactory parent = getParentBeanFactory();
                        if (parent instanceof ConfigurableBeanFactory) {
                            pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName);
                        }
                        else {
                            throw new NoSuchBeanDefinitionException(parentBeanName,
                                    "Parent name '" + parentBeanName + "' is equal to bean name '" + beanName +
                                    "': cannot be resolved without an AbstractBeanFactory parent");
                        }
                    }
                }
                catch (NoSuchBeanDefinitionException ex) {
                    throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName,
                            "Could not resolve parent bean definition '" + bd.getParentName() + "'", ex);
                }
                // Deep copy with overridden values.
                // Step3.3:使用父BeanDefinition定义new一个mbd定义,然后在将BeanDefinition定义覆盖到mbd上。
                mbd = new RootBeanDefinition(pbd);
                mbd.overrideFrom(bd);
            }

            // Set default singleton scope, if not configured before.
            // Step4:设置默认scope属性
            if (!StringUtils.hasLength(mbd.getScope())) {
                mbd.setScope(RootBeanDefinition.SCOPE_SINGLETON);
            }

            // A bean contained in a non-singleton bean cannot be a singleton itself.
            // Let's correct this on the fly here, since this might be the result of
            // parent-child merging for the outer bean, in which case the original inner bean
            // definition will not have inherited the merged outer bean's singleton status.
            if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {
                mbd.setScope(containingBd.getScope());
            }

            // Cache the merged bean definition for the time being
            // (it might still get re-merged later on in order to pick up metadata changes)
            // Step5:将创建出来的mbd定义放入mergedBeanDefinitions本地缓存
            if (containingBd == null && isCacheBeanMetadata()) {
                this.mergedBeanDefinitions.put(beanName, mbd);
            }
        }
        // Step6:返回mbd定义
        return mbd;
    }
}

BeanDefinition定义转换成RootBeanDefinition定义。主要是两种方式,关于二者的区别读者朋友自行查阅相关说明。

  • 一种是 clone 的方式
  • 一种是 new 的方式

4.doCreateBean() 流程分析

5.doCreateBean() 源码分析

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

    // Instantiate the bean.
    BeanWrapper instanceWrapper = null;
    // Step1:从缓存中获取
    if (mbd.isSingleton()) {
        instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
    }
    if (instanceWrapper == null) {
        // Step2:手动创建bean实例
        instanceWrapper = createBeanInstance(beanName, mbd, args);
    }
    // Step3:获取bean实例和对应的class 
    final Object bean = instanceWrapper.getWrappedInstance();
    Class<?> beanType = instanceWrapper.getWrappedClass();
    if (beanType != NullBean.class) {
        mbd.resolvedTargetType = beanType;
    }

    // Allow post-processors to modify the merged bean definition.
    // Step4:如果BeanPostProcessor还没有执行,则在此时执行一次bean后置处理器来修改mbd定义
    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.isDebugEnabled()) {
            logger.debug("Eagerly caching bean '" + beanName +
                    "' to allow for resolving potential circular references");
        }
        // Step5:第一步获取当前bean实例的依赖,如果没有则返回自己
        // 第二步将获取到的bean实例添加到本地缓存中,正是通过这种方式解决了bean实例的循环依赖问题。
        // 如果不能理解,文末提供例子在来说明。
        addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
    }

    // Initialize the bean instance.
    Object exposedObject = bean;
    try {
        // Step6:填充bean实例的属性
        populateBean(beanName, mbd, instanceWrapper);
        // Step7:初始化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 " +
                            "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
                }
            }
        }
    }

    // Register bean as disposable.
    try {
        // Step8:将创建出来的bean实例注册到BeanFactory里面。
        registerDisposableBeanIfNecessary(beanName, bean, mbd);
    }
    catch (BeanDefinitionValidationException ex) {
        throw new BeanCreationException(
                mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
    }
    // Step9:返回bean实例。
    return exposedObject;
}

6.getObjectForBeanInstance() 源码分析

protected Object getObjectForBeanInstance(
			Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {

    // Don't let calling code try to dereference the factory if the bean isn't a factory.
    // Step1:如果当前bean是以 “&”开头的并且是NullBean,则直接返回bean实例。
    if (BeanFactoryUtils.isFactoryDereference(name)) {
        if (beanInstance instanceof NullBean) {
            return beanInstance;
        }
        if (!(beanInstance instanceof FactoryBean)) {
            throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
        }
    }

    // Now we have the bean instance, which may be a normal bean or a FactoryBean.
    // If it's a FactoryBean, we use it to create a bean instance, unless the
    // caller actually wants a reference to the factory.
    // Step2:当前bean实例是普通bean || 是以“&”开头的普通bean,则直接返回bean实例。
    if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
        return beanInstance;
    }

    Object object = null;
    if (mbd == null) {
        // Step3:从缓存中获取bean实例。
        object = getCachedObjectForFactoryBean(beanName);
    }
    if (object == null) {
        // Return bean instance from factory.
        // Step4:从缓存中没有取到,则使用FactoryBean调用getObject()方法获取目标bean实例。
        FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
        // Caches object obtained from FactoryBean if it is a singleton.
        if (mbd == null && containsBeanDefinition(beanName)) {
            mbd = getMergedLocalBeanDefinition(beanName);
        }
        boolean synthetic = (mbd != null && mbd.isSynthetic());
        object = getObjectFromFactoryBean(factory, beanName, !synthetic);
    }
    // Step5:返回目标bean实例。
    return object;
}

该方法的主要作用其实一目了然,就是针对特殊的FactoryBean实例调用getObject()方法来获取目标bean实例。

7. 循环依赖解决方案剖析

假设现在有两个类,分别是 ClassA 和 ClassB,ClassA 有一个属性是 ClassB,ClassB 有一个属性是 ClassA。Spring 初始化的流程如下:

  1. 假设先初始化 ClassA,Spring 框架会先创建出 ClassA 的对应的 beanA 实例,但需要注意的是,此时仅仅是创建 beanA实例,并没有开始填充其属性
  2. 然后 Spring 将创建好的beanA 实例放入缓存中
  3. 获取 beanA 依赖的其他 bean 实例,即 ClassB 对应的 beanB 实例,但此时 beanB 实例还没被创建出来
  4. 创建 beanB 实例,同样也是创建出来一个空的 bean 实例,此时发现 beanB 实例依赖 beanA,于是存本地缓存中查询 beanA 实例并且获取到了。
  5. 通过第 4 步创建好了 beanB 实例,并将其也放入本地缓存后返回
  6. 经过第 4、5 步后,beanA 实例依赖的 beanB 实例被创建出来,然后在接着初始化 beanA 实例了。

8. 总结

本文讲解了关于singleton类型的 bean 实例的初始化流程(特意强调了是 singleton 类型的,后面我们再来研究下prototype类型的循环依赖问题),稍微比较复杂一点,需要 debug 代码多研究研究;下一篇接着讲讲 bean 实例初始化后,执行属性填充等一系列操作,敬请期待。


Spring源码阅读之初始化"非懒加载bean"实例-4

0. 导读

上一篇文章分析完了bean实例的创建,本文接着来讲讲bean实例的初始化结尾工作,主要介绍一下几个方面。

  1. populateBean():bean实例的属性填充工作。
  2. autowireByName()和autowireByType():两种bean实例的注入方式。
  3. applyPropertyValues():对bean实例填充相关的属性值。
  4. initializeBean():初始化bean实例。

1. 流程总览

2.populateBean() 流程分析

3.autowireByName() 流程分析

4.autowireByType() 流程分析

5.applyPropertyValues() 流程分析

6.initializeBean() 流程分析

7.invokeInitMethods() 流程分析

8. 总结

关于上一篇和这篇源码中,多次遇到了InstantiationAwareBeanPostProcessor和SmartInstantiationAwareBeanPostProcessor两个类,以防大家混淆,在这里特别说明一下。

  • 类图继承关系如下:
  • 关于两个接口提供的方法说明。
  • InstantiationAwareBeanPostProcessor接口方法说明
  • postProcessBeforeInstantiation():在bean实例创建前被调用,在这个时候可以使用动态代理创建bean实例等操作。
  • postProcessAfterInstantiation():在bean实例创建后,属性设置前被调用,给出机会修改bean实例的状态。
  • postProcessPropertyValues():主要作用是在设置属性前,用于修改属性值。
  • SmartInstantiationAwareBeanPostProcessor接口方法说明
  • predictBeanType():预测beanName对应的Class属性是否为指定的Class,如果是返回Class属性,反之返回null。
  • determineCandidateConstructors():如果beanName对应的Class有多个构造器,则通过该方法来确定使用哪个构造器来创建bean实例,如果没有指定构造器,则使用默认的构造器来创建bean实例。
  • getEarlyBeanReference():获取提前暴露的bean实例的引用,该方法主要用于解决scope类型为singleton的bean实例创建时面临的循环依赖问题。只有singleton的bean实例创建才会调用该方法。

到此,BeanDefinition定义解析和bean实例的初始化流程基本上就圆满完成了。下一篇我们开始一个新的概念,AOP思想在Spring框架中是怎么被运用的,敬请期待。(本文来自公众号:z小赵

感谢大家支持,多多转发关注小编不迷路~~~~~~~

最近发表
标签列表