A detailed explanation of Spring Boot's process of creating beans

A bean, as used when discussing Spring, refers to a Java class object hosted in a Spring container (or IoC container). The scope of Bean is divided into Singleton and Prototype (spring-web adds request\session, etc.). By default, a bean is scoped to Singleton. When the IoC container starts, the Singleton Bean is created and initialized by default. This process is called "eager registration of singletons". The process of creating a Singleton Bean in Spring can be divided into three stages:

  1. In the instantiation phase, AbstractAutowireCapableBeanFactory#createBeanInstance, this phase will call the constructor, factory method, etc. to complete the instantiation of the Bean.
  2. The attribute setting phase, AbstractAutowireCapableBeanFactory#populateBean, this phase will set dependencies.
  3. In the initialization phase, AbstractAutowireCapableBeanFactory#initializeBean, if the initialization method of the Bean instance is set, it will be called in this phase.

Next, I will analyze the above three stages one by one, and study with you the implementation source code of each process in Spring.

01-createBeanInstance

First, the process of creating a Bean is implemented in the AbstractAutowireCapableBeanFactory#createBeanInstance method. Its main function is to instantiate the Singleton Bean, for example, by calling the class constructor, factory method, and so on. The instantiated Bean is returned through a wrapping class BeanWrapper object. Next, let's look at the source code implementation of this part:

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
    /**
    * 一般来说,这里得到的就是要创建的 Bean 的类型,或者是它的工厂类类型
    */
    // Make sure bean class is actually resolved at this point.
    Class<?> beanClass = resolveBeanClass(mbd, beanName);   

    /**
    * 如果有 supplier,则使用 supplier 获得实例
    */
    Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
    if (instanceSupplier != null) {
        return obtainFromSupplier(instanceSupplier, beanName);
    }

    /**
    * 根据工厂类、工厂方法获得实例
    * 最终交由 ConstructorResolver#instantiateUsingFactoryMethod 方法实现
    */
    if (mbd.getFactoryMethodName() != null) {
        return instantiateUsingFactoryMethod(beanName, mbd, args);
    }

    /**
    * 如果前面两种方式都没能创建实例,则需要根据要创建 Bean 的构造器来实例化
    * args 是要使用的构造器参数
    * 如果 args == null,说明要使用默认够构造器
    */
    // Shortcut when re-creating the same 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) {
            /**
            * 对构造方法中需要自动注入的进行处理
            * 最终交由 ConstructorResolver#autowireConstructor 处理
            */
            return autowireConstructor(beanName, mbd, null, null);
        }
        else {
            /**
            * 使用默认够构造器
            * 根据实例化策略(SimpleInstantiationStrategy 或 CglibSubclassingInstantiationStrategy)来创建实例
            * 然后返回 BeanWrapper 对象
            */
            return instantiateBean(beanName, mbd);
        }
    }

    /**
    * 这里应对的是 args != null 的情况
    * 与前面一样,也是分为两种情况考虑:
    * 1. 对于需要 autowiring 的情况,由 ConstructorResolver#autowireConstructor 处理
    * 2. 其他情况,直接调用构造器创建对象
    */
    // 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);
}
复制代码

In the above source code implementation, there are a few points that need special attention:

  1. Supplier is a functional interface provided after Java 1.8. It only defines a get method to obtain the result. An instanceSupplier is defined in AbstractBeanDefinition, and through this callback, an instance of a specific Bean can be created. It should be reminded that creating Bean instances through instanceSupplier is a function supported since Spring 5.0. Moreover, its priority is higher than that of constructors and factory methods.
  2. If no Supplier is provided, an attempt is made to create a Bean instance through a factory class, factory method, or class constructor. For the case of using the parameterless constructor, create an instance directly according to the instantiation strategy (for example, based on CGLIB) BeanUtils#instantiateClass-> Constructor#newInstance. For the use of factory classes, factory methods or constructors with parameters, it is implemented by an auxiliary class ConstructorResolver inside Spring.
    • instantiateUsingFactoryMethod, through the factory method to instantiate the class. The factory method may be a static class method or a factory class object.
    • autowireConstructor, automatically assemble the corresponding constructor parameters from the container.

After instantiation, Spring populates the properties of the Bean (BeanWrapper) instance. This part of the code is implemented in AbstractAutowireCapableBeanFactory#populateBean. Next, let us study this part of the source code together.

02-populateBean

The main function of the AbstractAutowireCapableBeanFactory#populateBean method is to set (fill) the Bean instance in the BeanWrapper according to the property value in the BeanDefinition:

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {

    /**
    * 当使用 XML 文件作为配置文件时,<bean> 标签中的 <property> 中的内容,会设置到 BeanDefinition 的 PropertyValues 中
    * 当使用 @Configuration 类文件作为配置时,pvs 一般是空值
    */
    PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);

    /**
    * 这里的代码主要是检查 bw 中的引用类型(即依赖的其他 Bean)
    * 并且,从容器中获取(容器中不存在时会触发创建)这些 Bean,设置到 newPvs 中
    * 最终,applyPropertyValues 中,根据 newPvs 的值,设置 bw 中的属性值
    * 根据使用自动注入类型不同,区分为按类型注入、按 Bean 名称注入两种方式
    * 需要注意的是,这里并不会真正的修改 bw 中 Bean 的属性值
    */
    int resolvedAutowireMode = mbd.getResolvedAutowireMode();
    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) {
            /**
            * 根据 bean name 注入依赖,后面会讲到
            */
            autowireByName(beanName, mbd, bw, newPvs);
        }
        // Add property values based on autowire by type if applicable.
        if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
            /**
            * 与根据 bean name 注入类似
            */
            autowireByType(beanName, mbd, bw, newPvs);
        }
        pvs = newPvs;
    }

    /**
    * 这里会回调 InstantiationAwareBeanPostProcessor 中的 postProcessProperties
    */
    boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
    boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);

    PropertyDescriptor[] filteredPds = null;
    if (hasInstAwareBpps) {
        if (pvs == null) {
            pvs = mbd.getPropertyValues();
        }
        for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
            /**
            * 当使用 AnnotationConfigApplicationContext 时,一个关键的 InstantiationAwareBeanPostProcessor 实现是 AutowiredAnnotationBeanPostProcessor
            * 后者会处理 bw 包装的 Bean 类型中的 @Autowired、@Value、@Inject 注解的 Field、Method,并收集到 InjectionMetadata
            * 之后,会调用 InjectionMetadata#inject,完成依赖对象(值、其他 Bean)的注入
            */
            PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
            if (pvsToUse == null) {
                if (filteredPds == null) {
                    filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
                }
                /**
                * 从 5.1 版本起被废弃,推荐使用同接口中的 postProcessProperties 
                */
                pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
                if (pvsToUse == null) {
                    return;
                }
            }
            pvs = pvsToUse;
        }
    }
    /**
    * 执行依赖检查,确认是否所有的属性(除那些被特别排除的外)都被设置
    * 若有未设置的,会抛异常 UnsatisfiedDependencyException
    */
    if (needsDepCheck) {
        if (filteredPds == null) {
            filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
        }
        checkDependencies(beanName, mbd, filteredPds, pvs);
    }
    /**
    * 这里把 pvs 中的值设置到 bw 中的 Bean 实例中
    */
    if (pvs != null) {
        applyPropertyValues(beanName, mbd, bw, pvs);
    }
}
复制代码

In the above source code implementation, there are a few points that need special attention:

  1. autowireByName method, its source code is as follows. It iterates through all unsatisfied properties and then tries to get these references from the container, thus triggering the loading of other beans.
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
    for (String propertyName : propertyNames) {
        // 容器中有特定的 Bean
        if (containsBean(propertyName)) {
            Object bean = getBean(propertyName);
            // 获取(可能会出发 Bean 创建)对应 Bean,然后放入 pvs 中,等待后续真正设置到 bean 中属性里
            pvs.add(propertyName, bean);
            registerDependentBean(propertyName, beanName);
        }
        else {
        }
    }
复制代码

The unsatisfiedNonSimpleProperties method here will obtain all unsatisfied and non-simple types (simple types refer to basic types, enum, etc.) property values ​​of the internal bean instance from bw. For example:

public class Person {
    private String name;
    private String sex;
    // 省略 getter\setter
}
复制代码

Its corresponding unsatisfiedNonSimpleProperties method returns values ​​including name, sex, class, etc. It is important to note that without getter and setter methods, this property will not appear in the return value list. 2. In Spring, there are many interface definitions in the form of xxxPostProcessors. This is a life cycle callback mechanism provided by Spring, which allows users to participate in the Spring process by providing a specific implementation of xxxPostProcessor to implement specific processing logic. I personally think that this is a very flexible customization mechanism. When developing your own system, you can learn from and refer to this method of Spring.

When all required properties are populated, the Bean instance is considered available. However, for some more complex beans, it may be necessary to perform some initialization steps before they can actually provide external services. Spring will call the Bean's initialization method in the next stage.

03-initializeBean

Calling the initialization method of the Bean is implemented in AbstractAutowireCapableBeanFactory#initializeBean.

/**
* bean 就是前面两步创建好的 Bean 实例
*/
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
    
    /**
    * 如果 Bean 实现了 Aware 接口,调用它们定义的方法:
    * 1. BeanNameAware#setBeanName
    * 2. BeanClassLoaderAware#setBeanClassLoader
    * 3. BeanFactoryAware#setBeanFactory
    */
    invokeAwareMethods(beanName, bean);

    /**
    * 对于应用程序定义的 Bean,调用 BeanPostProcessor#postProcessBeforeInitialization 方法
    * 这个方法就是常被提到的 Bean 生命周期回调之一
    * 这里用到的也是前面提到的 PostProcessor 模式
    */
    Object wrappedBean = bean;
    if (mbd == null || !mbd.isSynthetic()) {  // synthetic 指不是由应用本身定义的,例如由容器定义的
        wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    }
    try {
        /**
        * 调用 Bean 的初始化方法
        * 对于 XML 配置文件来说,就是 <bean> 标签中指定的 init-method 方法
        * 对于 Java 类配置来说,@Bean 注解中的 initMethod 指定的方法
        * 对于实现了 InitializingBean 接口的 Bean 来说,调用 afterPropertiesSet 方法
        * 
        */
        invokeInitMethods(beanName, wrappedBean, mbd);
    }
    catch (Throwable ex) {  }
    /**
    * 对于应用程序定义的 Bean,调用 BeanPostProcessor#applyBeanPostProcessorsAfterInitialization 方法
    * 这个方法就是常被提到的 Bean 生命周期回调之一
    */
    if (mbd == null || !mbd.isSynthetic()) {
        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }
    return wrappedBean;
}
复制代码

So far, Spring's process of creating beans is basically over.

Guess you like

Origin blog.csdn.net/ww2651071028/article/details/130525003