Spring 源码学习 15:finishBeanFactoryInitialization(重点)

简介: 可以说前面的都是准备工作,而接下来开始的才是重点,在这一步会完成 BeanFactory 的初始化,同时实例化单例 Bean。具体怎么操作的,那就一起阅读源码吧!不过在阅读源码之前,还是需要了解一些知识的。1. 什么是 FactoryBean ?2. FactoryBean 是如何使用的 ?3. Bean 是如何初始化的?4. 常说的循环依赖是怎么解决的?

前言


可以说前面的都是准备工作,而接下来开始的才是重点,在这一步会完成 BeanFactory 的初始化,同时实例化单例 Bean。

具体怎么操作的,那就一起阅读源码吧!

不过在阅读源码之前,还是需要了解一些知识的。

  1. 什么是 FactoryBean ?
  2. FactoryBean 是如何使用的 ?
  3. Bean 是如何初始化的?
  4. 常说的循环依赖是怎么解决的?


什么是 FactoryBean ?

在官网的这篇文章《What's a FactoryBean?》中有相关解答,有兴趣的小伙伴可以看一下。

由内部使用的对象实现的接口,这些对象 BeanFactory 本身就是单个对象的工厂。如果 bean 实现此接口,则它将用作对象公开的工厂,而不是直接用作将自身公开的 bean 实例。

注意:实现此接口的 bean 不能用作普通 bean。 FactoryBean以 bean 样式定义,但是为 bean 引用(getObject())公开的对象始终是它创建的对象。

FactoryBeans 可以支持单例和原型,并且可以按需延迟创建对象,也可以在启动时急于创建对象。

当生命一个 FactoryBean 时,会存在两个类型的 Bean,分别是 FactoryBean 本身,以及它需要创建的类型的 Bean。

下面是使用示例:


使用


1. PaidComponent

public class PaidComponent {
  public PaidComponent() {
    System.out.println("PaidComponent 无参构造被调用");
  }
}


2. PaidComponentFactoryBean

@Component
public class PaidComponentFactoryBean implements FactoryBean<PaidComponent> {
  @Override
  public PaidComponent getObject() throws Exception {
    System.out.println("PaidComponentFactoryBean 的 getObject 方法被调用");
    return new PaidComponent();
  }
  @Override
  public Class<?> getObjectType() {
    return PaidComponent.class;
  }
}


3 Test

public class AnnotationConfigApplicationTest {
  public static void main(String[] args) {
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
    context.register(JavaConfig.class);
    context.refresh();
    System.out.println(context.getBean("paidComponentFactoryBean"));
    System.out.println(context.getBean("&paidComponentFactoryBean"));
    System.out.println(context.getBean(PaidComponent.class));
  }
}

网络异常,图片无法展示
|

可以看出注册了两个 Bean, 一个是 paidComponentFactoryBean ,另一个是 &paidComponentFactoryBean

而直接获取 paidComponentFactoryBean 获取到的其实是 FactoryBean 的 getObject() 方法返回的类型。


finishBeanFactoryInitialization 源码

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
    // Initialize conversion service for this context.
    // 初始化类型转换器
    if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
            beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
        beanFactory.setConversionService(
                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,以便尽早注册其转换器。
    String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
    for (String weaverAwareName : weaverAwareNames) {
        getBean(weaverAwareName);
    }
    // Stop using the temporary ClassLoader for type matching.
    // 停止使用临时的ClassLoader进行类型匹配。
    beanFactory.setTempClassLoader(null);
    // Allow for caching all bean definition metadata, not expecting further changes.
    // 设置 beanDefinition 元数据 不可以再修改
    beanFactory.freezeConfiguration();
    // Instantiate all remaining (non-lazy-init) singletons.
    // 实例化单例 bean
    beanFactory.preInstantiateSingletons();
}

这里重点关注最后一行

beanFactory.preInstantiateSingletons();


preInstantiateSingletons

这块进入的是类  DefaultListableBeanFactory 类的源码。

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.
    // 将 beanDefinitionNames 放到集合中
    List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
    // Trigger initialization of all non-lazy singleton beans...
    // 遍历
    for (String beanName : beanNames) {
        // 获取 bd 信息, 因为可能 定义了 parentBeanDefinition
        RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
        // 非抽象, 单例, 且不是懒加载
        if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
            // 判断是否为 FactoryBean
            if (isFactoryBean(beanName)) {
                // FactoryBean 需要添加前缀 & ,通过 getBean(&beanName) 获取的是 FactoryBean 本身
                Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
                if (bean instanceof FactoryBean) {
                    FactoryBean<?> factory = (FactoryBean<?>) bean;
                    // 判断是否需要初始化
                    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 {
                getBean(beanName);
            }
        }
    }
    // Trigger post-initialization callback for all applicable beans...
    // 如果 Bean 实现了 SmartInitializingSingleton,
    // 在这里会统一调用 afterSingletonsInstantiated 方法
    for (String beanName : beanNames) {
        Object singletonInstance = getSingleton(beanName);
        if (singletonInstance instanceof SmartInitializingSingleton) {
            StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize")
                    .tag("beanName", beanName);
            SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
            if (System.getSecurityManager() != null) {
                AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                    smartSingleton.afterSingletonsInstantiated();
                    return null;
                }, getAccessControlContext());
            }
            else {
                smartSingleton.afterSingletonsInstantiated();
            }
            smartInitialize.end();
        }
    }
}

上面方法中通过循环 beanNames 进行初始化 Bean。

其中需要区别 BeanFactory 和 普通 Bean。 这也是我开始为什么先介绍了什么是 BeanFactory ?

下面就需要重点关注 getBean(beanName) 方法。


getBean

public Object getBean(String name) throws BeansException {
    return doGetBean(name, null, null, false);
}

getBean 方法中调用的是 doGetBean 方法。


doGetBean

doGetBean 方法作用是:返回一个实例,该实例可以是指定bean的共享或独立的

该方法接受四个参数:

name – 要检索的 bean 的名称 requiredType – 要检索的 bean 的必需类型,这个可以为空 args –使用显式参数创建bean实例时要使用的参数(仅在创建新实例而不是检索现有实例时才应用) typeCheckOnly –是否为类型检查而不是实际使用获取实例

protected <T> T doGetBean(
        String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
        throws BeansException {
    // 去掉工厂引用的前缀, 同时转换别名
    String beanName = transformedBeanName(name);
    Object bean;
    // Eagerly check singleton cache for manually registered singletons.
    // 从缓存中检查单例是否已经存在
    Object sharedInstance = getSingleton(beanName);
    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 直接返回, FactoryBean 则返回 FactoryBean 创建的 Bean
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    }
    else {
        // Fail if we're already creating this bean instance:
        // We're assumably within a circular reference.
        // 返回指定的 原型bean (prototype 类型的 Bean) 是否当前正在创建中(在当前线程内)。
        if (isPrototypeCurrentlyInCreation(beanName)) {
            throw new BeanCurrentlyInCreationException(beanName);
        }
        // Check if bean definition exists in this factory.
        // 检查 BeanFactory 是否存在这个 Bean 的 BeanDefinition
        BeanFactory parentBeanFactory = getParentBeanFactory();
        if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
            // Not found -> check parent.
            // 检查父容器中有没有定义
            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) {
            // 将当前 beanName 放入一个 alreadyCreated 的 Set 集合中。
            // 标识本次调用方法,并非是要获取bean的类型,而是为了创建实例,将beanName存到alreadyCreated集合,代表该bean已经创建了,后面try。。catch有异常会清空该beanName
            markBeanAsCreated(beanName);
        }
        StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")
                .tag("beanName", name);
        try {
            if (requiredType != null) {
                beanCreation.tag("beanType", requiredType::toString);
            }
            // 获取 Bean 的 BeanDefinition
            RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
            checkMergedBeanDefinition(mbd, beanName, args);
            // Guarantee initialization of beans that the current bean depends on.
            // 确保依赖的 Bean 已经被初始化, 比如 @DependsOn 注解
            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 {
                        // 创建依赖的 Bean
                        getBean(dep);
                    }
                    catch (NoSuchBeanDefinitionException ex) {
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
                    }
                }
            }
            // Create bean instance.
            if (mbd.isSingleton()) {
                // 单例 bean
                sharedInstance = getSingleton(beanName, () -> {
                    try {
                        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);
            }
            // 创建原型Bean
            else if (mbd.isPrototype()) {
                // It's a prototype -> create a new instance.
                Object prototypeInstance = null;
                try {
                    beforePrototypeCreation(beanName);
                    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 ScopeNotActiveException(beanName, scopeName, ex);
                }
            }
        }
        catch (BeansException ex) {
            beanCreation.tag("exception", ex.getClass().toString());
            beanCreation.tag("message", String.valueOf(ex.getMessage()));
            cleanupAfterBeanCreationFailure(beanName);
            throw ex;
        }
        finally {
            beanCreation.end();
        }
    }
    // Check if required type matches the type of the actual bean instance.
    // 检查所需的类型是否与实际bean实例的类型匹配。
    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;
}

上面代码比较长,基本上步骤已经添加相应的注释,基本上可以分为三步:

  1. 从缓存中获取到 Bean,创建对应的 Bean;
  2. 没有从缓存中获取到 Bean,创建对应的 Bean;
  3. 检查所需的类型是否与实际bean实例的类型匹配。


下面从这三个步骤分别介绍:

  • 从缓存中获取到 Bean,创建对应的 Bean

Object sharedInstance = getSingleton(beanName);

public Object getSingleton(String beanName) {
    return getSingleton(beanName, true);
}
/**
 * 返回以给定名称注册的(原始)单例对象。
 *
 * 检查已经实例化的单例,并允许早期引用当前创建的单例(解析循环引用)
 */
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    // Quick check for existing instance without full singleton lock
    // private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
    // 缓存了 单例 Bean
    Object singletonObject = this.singletonObjects.get(beanName);
    // 如果没有获取到, 并且当前 Bean 正在被创建中
    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
        // private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);
        // 早期的单例对象, 先从 earlySingletonObjects 中获取
        singletonObject = this.earlySingletonObjects.get(beanName);
        // 没有从 earlySingletonObjects 缓存中获取到
        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) {
                        // private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
                        // 从 singletonFactories 缓存中获取
                        ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                        if (singletonFactory != null) {
                            singletonObject = singletonFactory.getObject();
                            // 添加到 earlySingletonObjects 缓存中
                            this.earlySingletonObjects.put(beanName, singletonObject);
                            // 从 singletonFactories 缓存中删除
                            this.singletonFactories.remove(beanName);
                        }
                    }
                }
            }
        }
    }
    return singletonObject;
}

这里可以看出,获取一个 Bean :

  1. 先从 singletonObjects 中获取 Bean;
  2. 获取不到,从 earlySingletonObjects 中获取 Bean;
  3. 获取不到,从 singletonFactories 中获取 Bean。


当然这一块涉及到循环引用,篇幅有限,后面会专门介绍循环引用。

  • 没有从缓存中获取到 Bean,创建对应的 Bean
// Create bean instance.
if (mbd.isSingleton()) {
    // 单例 bean
    sharedInstance = getSingleton(beanName, () -> {
        try {
            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);
} else if (mbd.isPrototype()) {
    // 创建原型Bean
} else {
    // 委托给实现类处理
    String scopeName = mbd.getScope();
}
  • 检查所需的类型是否与实际bean实例的类型匹配


总结


这里主要介绍了 Bean 的创建过程,主要是对整个过程有个大概的了解和熟悉,针对过程画图如下:

网络异常,图片无法展示
|

其中 Bean 的实例化主要关注单例 Bean 的实例化,后面准备对其进行详细研究后,再进行说明。

目录
相关文章
|
11天前
|
数据采集 监控 前端开发
二级公立医院绩效考核系统源码,B/S架构,前后端分别基于Spring Boot和Avue框架
医院绩效管理系统通过与HIS系统的无缝对接,实现数据网络化采集、评价结果透明化管理及奖金分配自动化生成。系统涵盖科室和个人绩效考核、医疗质量考核、数据采集、绩效工资核算、收支核算、工作量统计、单项奖惩等功能,提升绩效评估的全面性、准确性和公正性。技术栈采用B/S架构,前后端分别基于Spring Boot和Avue框架。
|
1天前
|
前端开发 Java 开发者
Spring生态学习路径与源码深度探讨
【11月更文挑战第13天】Spring框架作为Java企业级开发中的核心框架,其丰富的生态系统和强大的功能吸引了无数开发者的关注。学习Spring生态不仅仅是掌握Spring Framework本身,更需要深入理解其周边组件和工具,以及源码的底层实现逻辑。本文将从Spring生态的学习路径入手,详细探讨如何系统地学习Spring,并深入解析各个重点的底层实现逻辑。
20 9
|
21天前
|
前端开发 Java 数据库
SpringBoot学习
【10月更文挑战第7天】Spring学习
33 9
|
22天前
|
XML Java 数据格式
Spring学习
【10月更文挑战第6天】Spring学习
19 1
|
27天前
|
Java Spring
Spring底层架构源码解析(三)
Spring底层架构源码解析(三)
|
27天前
|
XML Java 数据格式
Spring底层架构源码解析(二)
Spring底层架构源码解析(二)
|
26天前
|
Java 测试技术 开发者
springboot学习四:Spring Boot profile多环境配置、devtools热部署
这篇文章主要介绍了如何在Spring Boot中进行多环境配置以及如何整合DevTools实现热部署,以提高开发效率。
51 2
|
26天前
|
前端开发 Java 程序员
springboot 学习十五:Spring Boot 优雅的集成Swagger2、Knife4j
这篇文章是关于如何在Spring Boot项目中集成Swagger2和Knife4j来生成和美化API接口文档的详细教程。
47 1
|
26天前
|
Java API Spring
springboot学习七:Spring Boot2.x 拦截器基础入门&实战项目场景实现
这篇文章是关于Spring Boot 2.x中拦截器的入门教程和实战项目场景实现的详细指南。
19 0
springboot学习七:Spring Boot2.x 拦截器基础入门&实战项目场景实现
|
26天前
|
Java API Spring
springboot学习六:Spring Boot2.x 过滤器基础入门&实战项目场景实现
这篇文章是关于Spring Boot 2.x中过滤器的基础知识和实战项目应用的教程。
21 0
springboot学习六:Spring Boot2.x 过滤器基础入门&实战项目场景实现