• 《深入浅出Spring》bean 生命周期


    Spring bean生命周期12个环节

    阶段1:Bean元信息配置阶段
    阶段2:Bean元信息解析阶段
    阶段3:将Bean注册到容器中
    阶段4:BeanDefinition合并阶段
    阶段5:Bean Class加载阶段
    阶段6:Bean实例化阶段(2个小阶段)
    Bean实例化前阶段
    Bean实例化阶段
    阶段7:合并后的BeanDefinition处理
    阶段8:属性赋值阶段(3个小阶段)
    Bean实例化后阶段
    Bean属性赋值前阶段
    Bean属性赋值阶段
    阶段9:Bean初始化阶段(5个小阶段)
    Bean Aware接口回调阶段
    Bean初始化前阶段
    Bean初始化阶段
    Bean初始化后阶段
    阶段10:所有单例bean初始化完成后阶段
    阶段11:Bean的使用阶段
    阶段12:Bean销毁前阶段
    阶段13:Bean销毁阶段

    阶段1:Bean元信息配置阶段

    这个阶段主要是bean信息的定义阶段。

    Bean信息定义4种方式

    • API的方式
    • Xml文件方式
    • properties文件的方式
    • 注解的方式

    API的方式

    先来说这种方式,因为其他几种方式最终都会采用这种方式来定义bean配置信息。

    Spring容器启动的过程中,会将Bean解析成Spring内部的BeanDefinition结构。
    不管是是通过xml配置文件的标签,还是通过注解配置的@Bean,还是@Compontent标注的类,还是扫描得到的类,它最终都会被解析成一个BeanDefinition对象,最后我们的Bean工厂就会根据这份Bean的定义信息,对bean进行实例化、初始化等等操作。

    你可以把BeanDefinition丢给Bean工厂,然后Bean工厂就会根据这个信息帮你生产一个Bean实例,拿去使用。

    BeanDefinition里面里面包含了bean定义的各种信息,如:bean对应的class、scope、lazy信息、dependOn信息、autowireCandidate(是否是候选对象)、primary(是否是主要的候选者)等信息。

    BeanDefinition是个接口,有几个实现类,看一下类图:
    在这里插入图片描述
    BeanDefinition接口:bean定义信息接口
    表示bean定义信息的接口,里面定义了一些获取bean定义配置信息的各种方法,:

    public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
        /**
         * 设置此bean的父bean名称(对应xml中bean元素的parent属性)
         */
        void setParentName(@Nullable String parentName);
        /**
         * 返回此bean定义时指定的父bean的名称
         */
        @Nullable
        String getParentName();
        /**
         * 指定此bean定义的bean类名(对应xml中bean元素的class属性)
         */
        void setBeanClassName(@Nullable String beanClassName);
        /**
         * 返回此bean定义的当前bean类名
         * 注意,如果子定义重写/继承其父类的类名,则这不一定是运行时使用的实际类名。此外,这可能只是调用工厂方法的类,或者在调用方法的工厂bean引用的情况下,它甚至可能是空的。因此,不要认为这是运行时的最终bean类型,而只将其用于单个bean定义级别的解析目的。
         */
        @Nullable
        String getBeanClassName();
        /**
         * 设置此bean的生命周期,如:singleton、prototype(对应xml中bean元素的scope属性)
         */
        void setScope(@Nullable String scope);
        /**
         * 返回此bean的生命周期,如:singleton、prototype
         */
        @Nullable
        String getScope();
        /**
         * 设置是否应延迟初始化此bean(对应xml中bean元素的lazy属性)
         */
        void setLazyInit(boolean lazyInit);
        /**
         * 返回是否应延迟初始化此bean,只对单例bean有效
         */
        boolean isLazyInit();
        /**
         * 设置此bean依赖于初始化的bean的名称,bean工厂将保证dependsOn指定的bean会在当前bean初始化之前先初始化好
         */
        void setDependsOn(@Nullable String... dependsOn);
        /**
         * 返回此bean所依赖的bean名称
         */
        @Nullable
        String[] getDependsOn();
        /**
         * 设置此bean是否作为其他bean自动注入时的候选者
         * autowireCandidate
         */
        void setAutowireCandidate(boolean autowireCandidate);
        /**
         * 返回此bean是否作为其他bean自动注入时的候选者
         */
        boolean isAutowireCandidate();
        /**
         * 设置此bean是否为自动注入的主要候选者
         * primary:是否为主要候选者
         */
        void setPrimary(boolean primary);
        /**
         * 返回此bean是否作为自动注入的主要候选者
         */
        boolean isPrimary();
        /**
         * 指定要使用的工厂bean(如果有)。这是要对其调用指定工厂方法的bean的名称。
         * factoryBeanName:工厂bean名称
         */
        void setFactoryBeanName(@Nullable String factoryBeanName);
        /**
         * 返回工厂bean名称(如果有)(对应xml中bean元素的factory-bean属性)
         */
        @Nullable
        String getFactoryBeanName();
        /**
         * 指定工厂方法(如果有)。此方法将使用构造函数参数调用,如果未指定任何参数,则不使用任何参数调用。该方法将在指定的工厂bean(如果有的话)上调用,或者作为本地bean类上的静态方法调用。
         * factoryMethodName:工厂方法名称
         */
        void setFactoryMethodName(@Nullable String factoryMethodName);
        /**
         * 返回工厂方法名称(对应xml中bean的factory-method属性)
         */
        @Nullable
        String getFactoryMethodName();
        /**
         * 返回此bean的构造函数参数值
         */
        ConstructorArgumentValues getConstructorArgumentValues();
        /**
         * 是否有构造器参数值设置信息(对应xml中bean元素的<constructor-arg />子元素)
         */
        default boolean hasConstructorArgumentValues() {
            return !getConstructorArgumentValues().isEmpty();
        }
        /**
         * 获取bean定义是配置的属性值设置信息
         */
        MutablePropertyValues getPropertyValues();
        /**
         * 这个bean定义中是否有属性设置信息(对应xml中bean元素的<property />子元素)
         */
        default boolean hasPropertyValues() {
            return !getPropertyValues().isEmpty();
        }
        /**
         * 设置bean初始化方法名称
         */
        void setInitMethodName(@Nullable String initMethodName);
        /**
         * bean初始化方法名称
         */
        @Nullable
        String getInitMethodName();
        /**
         * 设置bean销毁方法的名称
         */
        void setDestroyMethodName(@Nullable String destroyMethodName);
        /**
         * bean销毁的方法名称
         */
        @Nullable
        String getDestroyMethodName();
        /**
         * 设置bean的role信息
         */
        void setRole(int role);
        /**
         * bean定义的role信息
         */
        int getRole();
        /**
         * 设置bean描述信息
         */
        void setDescription(@Nullable String description);
        /**
         * bean描述信息
         */
        @Nullable
        String getDescription();
        /**
         * bean类型解析器
         */
        ResolvableType getResolvableType();
        /**
         * 是否是单例的bean
         */
        boolean isSingleton();
        /**
         * 是否是多列的bean
         */
        boolean isPrototype();
        /**
         * 对应xml中bean元素的abstract属性,用来指定是否是抽象的
         */
        boolean isAbstract();
        /**
         * 返回此bean定义来自的资源的描述(以便在出现错误时显示上下文)
         */
        @Nullable
        String getResourceDescription();
        @Nullable
        BeanDefinition getOriginatingBeanDefinition();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163

    BeanDefinition接口上面还继承了2个接口:
    AttributeAccessor
    BeanMetadataElement

    AttributeAccessor接口:属性访问接口

    public interface AttributeAccessor {
        /**
         * 设置属性->值
         */
        void setAttribute(String name, @Nullable Object value);
        /**
         * 获取某个属性对应的值
         */
        @Nullable
        Object getAttribute(String name);
        /**
         * 移除某个属性
         */
        @Nullable
        Object removeAttribute(String name);
        /**
         * 是否包含某个属性
         */
        boolean hasAttribute(String name);
        /**
         * 返回所有的属性名称
         */
        String[] attributeNames();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    这个接口相当于key->value数据结构的一种操作,BeanDefinition继承这个,内部实际上是使用了LinkedHashMap来实现这个接口中的所有方法,通常我们通过这些方法来保存BeanDefinition定义过程中产生的一些附加信息。

    BeanMetadataElement接口
    看一下其源码:

    public interface BeanMetadataElement {
        @Nullable
        default Object getSource() {
            return null;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    RootBeanDefinition类:表示根bean定义信息
    通常bean中没有父bean的就使用这种表示

    ChildBeanDefinition类:表示子bean定义信息
    如果需要指定父bean的,可以使用ChildBeanDefinition来定义子bean的配置信息,里面有个parentName属性,用来指定父bean的名称。

    GenericBeanDefinition类:通用的bean定义信息
    既可以表示没有父bean的bean配置信息,也可以表示有父bean的子bean配置信息,这个类里面也有parentName属性,用来指定父bean的名称。

    ConfigurationClassBeanDefinition类:表示通过配置类中@Bean方法定义bean信息
    可以通过配置类中使用@Bean来标注一些方法,通过这些方法来定义bean,这些方法配置的bean信息最后会转换为ConfigurationClassBeanDefinition类型的对象

    AnnotatedBeanDefinition接口:表示通过注解的方式定义的bean信息
    里面有个方法

    AnnotationMetadata getMetadata();
    用来获取定义这个bean的类上的所有注解信息。

    BeanDefinitionBuilder:构建BeanDefinition的工具类
    spring中为了方便操作BeanDefinition,提供了一个类:BeanDefinitionBuilder,内部提供了很多静态方法,通过这些方法可以非常方便的组装BeanDefinition对象

    栗子1 组装一个有依赖关系的bean:

    public void test3() {
        //先创建car这个BeanDefinition
        BeanDefinition carBeanDefinition = BeanDefinitionBuilder.rootBeanDefinition(Car.class.getName()).addPropertyValue("name", "奥迪").getBeanDefinition();
        //创建User这个BeanDefinition
        BeanDefinition userBeanDefinition = BeanDefinitionBuilder.rootBeanDefinition(User.class.getName()).
                addPropertyValue("name", "test").
                addPropertyReference("car", "car"). //@1
                getBeanDefinition();
        //创建spring容器
        DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
        //调用registerBeanDefinition向容器中注册bean
        factory.registerBeanDefinition("car", carBeanDefinition); 
        factory.registerBeanDefinition("user", userBeanDefinition);
        System.out.println(factory.getBean("car"));
        System.out.println(factory.getBean("user"));
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    @1:注入依赖的bean,需要使用addPropertyReference方法,2个参数,第一个为属性的名称,第二个为需要注入的bean的名称

    上面代码等效于

    <bean id="car" class="com.yuan11.Car">
        <property name="name" value="奥迪"/>
    </bean>
    <bean id="user" class="com.yuan11.User">
        <property name="name" value="test"/>
        <property name="car" ref="car"/>
    </bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    栗子2 通过api设置(Map、Set、List)属性

    RuntimeBeanReference:用来表示bean引用类型,类似于xml中的ref

    ManagedList:属性如果是List类型的,t需要用到这个类进行操作,这个类继承了ArrayList

    ManagedSet:属性如果是Set类型的,t需要用到这个类进行操作,这个类继承了LinkedHashSet

    ManagedMap:属性如果是Map类型的,t需要用到这个类进行操作,这个类继承了LinkedHashMap

    Xml文件方式

    这种方式已经讲过很多次了,大家也比较熟悉,即通过xml的方式来定义bean,如下

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-4.3.xsd">
        <bean id="bean名称" class="bean完整类名"/>
    </beans>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    xml中的bean配置信息会被解析器解析为BeanDefinition对象,一会在第二阶段详解。

    properties文件的方式

    这种方式估计大家比较陌生,将bean定义信息放在properties文件中,然后通过解析器将配置信息解析为BeanDefinition对象。

    properties内容格式如下:

    employee.(class)=MyClass       // 等同于:<bean class="MyClass" />
    employee.(abstract)=true       // 等同于:<bean abstract="true" />
    employee.group=Insurance       // 为属性设置值,等同于:<property name="group" value="Insurance" />
    employee.usesDialUp=false      // 为employee这个bean中的usesDialUp属性设置值,等同于:等同于:<property name="usesDialUp" value="false" />
    salesrep.(parent)=employee     // 定义了一个id为salesrep的bean,指定父bean为employee,等同于:<bean id="salesrep" parent="employee" />
    salesrep.(lazy-init)=true      // 设置延迟初始化,等同于:<bean lazy-init="true" />
    salesrep.manager(ref)=tony     // 设置这个bean的manager属性值,是另外一个bean,名称为tony,等同于:<property name="manager" ref="tony" />
    salesrep.department=Sales      // 等同于:<property name="department" value="Sales" />
    techie.(parent)=employee       // 定义了一个id为techie的bean,指定父bean为employee,等同于:<bean id="techie" parent="employee" />
    techie.(scope)=prototype       // 设置bean的作用域,等同于<bean scope="prototype" />
    techie.manager(ref)=jeff       // 等同于:<property name="manager" ref="jeff" />
    techie.department=Engineering  // <property name="department" value="Engineering" />
    techie.usesDialUp=true         // <property name="usesDialUp" value="true" />
    ceo.$0(ref)=secretary          // 设置构造函数第1个参数值,等同于:<constructor-arg index="0" ref="secretary" />
    ceo.$1=1000000                 // 设置构造函数第2个参数值,等同于:<constructor-arg index="1" value="1000000" />
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    注解的方式

    常见的2种:

    类上标注@Compontent注解来定义一个bean
    配置类中使用@Bean注解来定义bean

    bean注册者只识别BeanDefinition对象,不管什么方式最后都会将这些bean定义的信息转换为BeanDefinition对象,然后注册到spring容器中。

    阶段2:Bean元信息解析阶段

    Bean元信息的解析就是将各种方式定义的bean配置信息解析为BeanDefinition对象。

    Bean元信息的解析主要有3种方式

    1. xml文件定义bean的解析
    2. properties文件定义bean的解析
    3. 注解方式定义bean的解析

    XML方式解析:XmlBeanDefinitionReader

    spring中提供了一个类XmlBeanDefinitionReader,将xml中定义的bean解析为BeanDefinition对象。xml中定义的bean被解析之后都是通过GenericBeanDefinition这种类型表示的。

    properties文件定义bean的解析:PropertiesBeanDefinitionReader

    spring中提供了一个类XmlBeanDefinitionReader,将xml中定义的bean解析为BeanDefinition对象,过程和xml的方式类似。

    注解方式:AnnotatedBeanDefinitionReader

    注解的方式定义的bean,需要使用PropertiesBeanDefinitionReader这个类来进行解析,方式也和上面2种方式类似,直接来看案例。

    阶段3:Spring Bean注册阶段

    bean注册阶段需要用到一个非常重要的接口:BeanDefinitionRegistry

    Bean注册接口:BeanDefinitionRegistry

    public interface BeanDefinitionRegistry extends AliasRegistry {
        /**
         * 注册一个新的bean定义
         * beanName:bean的名称
         * beanDefinition:bean定义信息
         */
        void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
                throws BeanDefinitionStoreException;
        /**
         * 通过bean名称移除已注册的bean
         * beanName:bean名称
         */
        void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
        /**
         * 通过名称获取bean的定义信息
         * beanName:bean名称
         */
        BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
        /**
         * 查看beanName是否注册过
         */
        boolean containsBeanDefinition(String beanName);
        /**
         * 获取已经定义(注册)的bean名称列表
         */
        String[] getBeanDefinitionNames();
        /**
         * 返回注册器中已注册的bean数量
         */
        int getBeanDefinitionCount();
        /**
         * 确定给定的bean名称或者别名是否已在此注册表中使用
         * beanName:可以是bean名称或者bean的别名
         */
        boolean isBeanNameInUse(String beanName);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    别名注册接口:AliasRegistry
    BeanDefinitionRegistry接口继承了AliasRegistry接口,这个接口中定义了操作bean别名的一些方法,

    public interface AliasRegistry {
        /**
         * 给name指定别名alias
         */
        void registerAlias(String name, String alias);
        /**
         * 从此注册表中删除指定的别名
         */
        void removeAlias(String alias);
        /**
         * 判断name是否作为别名已经被使用了
         */
        boolean isAlias(String name);
        /**
         * 返回name对应的所有别名
         */
        String[] getAliases(String name);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    BeanDefinitionRegistry唯一实现:DefaultListableBeanFactory
    spring中BeanDefinitionRegistry接口有一个唯一的实现类:

    org.springframework.beans.factory.support.DefaultListableBeanFactory
    
    • 1

    大家可能看到有很多类也实现了BeanDefinitionRegistry接口,比如我们经常用到的AnnotationConfigApplicationContext,但实际上其内部是转发给了DefaultListableBeanFactory进行处理的,所以真正实现这个接口的类是DefaultListableBeanFactory。

    阶段4:BeanDefinition合并阶段

    合并阶段是做什么的?
    可能我们定义bean的时候有父子bean关系,此时子BeanDefinition中的信息是不完整的,比如设置属性的时候配置在父BeanDefinition中,此时子BeanDefinition中是没有这些信息的,需要将子bean的BeanDefinition和父bean的BeanDefinition进行合并,得到最终的一个RootBeanDefinition,合并之后得到的RootBeanDefinition包含bean定义的所有信息,包含了从父bean中继继承过来的所有信息,后续bean的所有创建工作就是依靠合并之后BeanDefinition来进行的。

    合并BeanDefinition会使用下面这个方法:

    org.springframework.beans.factory.support.AbstractBeanFactory#getMergedBeanDefinition
    
    • 1

    bean定义可能存在多级父子关系,合并的时候进进行递归合并,最终得到一个包含完整信息的RootBeanDefinition

    合并之前是GenericBeanDefinition类型的,合并之后得到的是RootBeanDefinition类型的。
    后面的阶段将使用合并产生的RootBeanDefinition

    阶段5:Bean Class加载阶段

    这个阶段就是将bean的class名称转换为Class类型的对象。

    BeanDefinition中有个Object类型的字段:beanClass

    private volatile Object beanClass;
    
    • 1

    用来表示bean的class对象,通常这个字段的值有2种类型,一种是bean对应的Class类型的对象,另一种是bean对应的Class的完整类名,第一种情况不需要解析,第二种情况:即这个字段是bean的类名的时候,就需要通过类加载器将其转换为一个Class对象。

    此时会对阶段4中合并产生的RootBeanDefinition中的beanClass进行解析,将bean的类名转换为Class对象,然后赋值给beanClass字段。

    源码位置:

    org.springframework.beans.factory.support.AbstractBeanFactory#resolveBeanClass
    
    • 1

    上面得到了Bean Class对象以及合并之后的BeanDefinition,下面就开始进入实例化这个对象的阶段了。
    Bean实例化分为3个阶段:前阶段、实例化阶段、后阶段;下面详解介绍。

    阶段6:Bean实例化阶段

    分2个小的阶段

    • Bean实例化前操作
    • Bean实例化操作
    • Bean实例化前操作
      先来看一下DefaultListableBeanFactory,这个类中有个非常非常重要的字段:
    private final List<BeanPostProcessor> beanPostProcessors = new CopyOnWriteArrayList<>();
    
    • 1

    是一个BeanPostProcessor类型的集合

    BeanPostProcessor是一个接口,还有很多子接口,这些接口中提供了很多方法,spring在bean生命周期的不同阶段,会调用上面这个列表中的BeanPostProcessor中的一些方法,来对生命周期进行扩展,bean生命周期中的所有扩展点都是依靠这个集合中的BeanPostProcessor来实现的,所以如果大家想对bean的生命周期进行干预,这块一定要掌握好。

    注意:本文中很多以BeanPostProcessor结尾的,都实现了BeanPostProcessor接口,有些是直接实现的,有些是实现了它的子接口。

    Bean实例化之前会调用一段代码:

    @Nullable
        protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
            for (BeanPostProcessor bp : getBeanPostProcessors()) {
                if (bp instanceof InstantiationAwareBeanPostProcessor) {
                    InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                    Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
                    if (result != null) {
                        return result;
                    }
                }
            }
            return null;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    这段代码在bean实例化之前给开发者留了个口子,开发者自己可以在这个地方直接去创建一个对象作为bean实例,而跳过spring内部实例化bean的过程。

    上面代码中轮询beanPostProcessors列表,如果类型是InstantiationAwareBeanPostProcessor, 尝试调用InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation获取bean的实例对象,如果能够获取到,那么将返回值作为当前bean的实例,那么spring自带的实例化bean的过程就被跳过了。

    postProcessBeforeInstantiation方法如下:

    default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        return null;
    }
    
    • 1
    • 2
    • 3

    这个地方给开发者提供了一个扩展点,允许开发者在这个方法中直接返回bean的一个实例。

    栗子:

    //添加一个BeanPostProcessor:InstantiationAwareBeanPostProcessor
            factory.addBeanPostProcessor(new InstantiationAwareBeanPostProcessor() { //@1
                @Nullable
                @Override
                public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
                    System.out.println("调用postProcessBeforeInstantiation()");
                    //发现类型是Car类型的时候,硬编码创建一个Car对象返回
                    if (beanClass == Car.class) {
                        Car car = new Car();
                        car.setName("保时捷");
                        return car;
                    }
                    return null;
                }
            });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    @1方法中手动创建了一个实例直接返回了,而不是依靠spring内部去创建这个实例

    Bean实例化操作

    这个过程可以干什么?
    这个过程会通过反射来调用bean的构造器来创建bean的实例。
    具体需要使用哪个构造器,spring为开发者提供了一个接口,允许开发者自己来判断用哪个构造器。
    看一下这块的代码逻辑:

    for (BeanPostProcessor bp : getBeanPostProcessors()) {
        if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
            SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
            Constructor<?>[] ctors = ibp.determineCandidateConstructors(beanClass, beanName);
            if (ctors != null) {
                return ctors;
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    会调用SmartInstantiationAwareBeanPostProcessor接口的determineCandidateConstructors方法,这个方法会返回候选的构造器列表,也可以返回空,看一下这个方法的源码:

    @Nullable
    default Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName)
    throws BeansException {
        return null;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    这个方法有个比较重要的实现类

    org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor
    
    • 1

    阶段7:合并后的BeanDefinition处理

    这块的源码如下

    protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
            for (BeanPostProcessor bp : getBeanPostProcessors()) {
                if (bp instanceof MergedBeanDefinitionPostProcessor) {
                    MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
                    bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
                }
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    会调用MergedBeanDefinitionPostProcessor接口的postProcessMergedBeanDefinition方法,看一下这个方法的源码:

    void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName);
    
    • 1

    spring会轮询BeanPostProcessor,依次调用MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition

    第一个参数为beanDefinition,表示合并之后的RootBeanDefinition,我们可以在这个方法内部对合并之后的BeanDefinition进行再次处理

    postProcessMergedBeanDefinition有2个实现类,前面我们介绍过,用的也比较多,面试的时候也会经常问的:

    org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor
    
    • 1

    在 postProcessMergedBeanDefinition 方法中对 @Autowired、@Value 标注的方法、字段进行缓存

    org.springframework.context.annotation.CommonAnnotationBeanPostProcessor
    
    • 1

    在 postProcessMergedBeanDefinition 方法中对 @Resource 标注的字段、@Resource
    标注的方法、 @PostConstruct 标注的字段、 @PreDestroy标注的方法进行缓存

    阶段8:Bean属性设置阶段

    属性设置阶段分为3个小的阶段

    • 实例化后阶段
    • Bean属性赋值前处理
    • Bean属性赋值

    实例化后阶段

    会调用InstantiationAwareBeanPostProcessor接口的postProcessAfterInstantiation这个方法,调用逻辑如下:

    看一下具体的调用逻辑如下:

    for (BeanPostProcessor bp : getBeanPostProcessors()) {
        if (bp instanceof InstantiationAwareBeanPostProcessor) {
            InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
            if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                return;
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    postProcessAfterInstantiation方法返回false的时候,后续的Bean属性赋值前处理、Bean属性赋值都会被跳过了。

    来看一下postProcessAfterInstantiation这个方法的定义

    default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        return true;
    }
    
    • 1
    • 2
    • 3

    Bean属性赋值前阶段

    这个阶段会调用InstantiationAwareBeanPostProcessor接口的postProcessProperties方法,调用逻辑:

    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);
                }
                pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
                if (pvsToUse == null) {
                    return;
                }
            }
            pvs = pvsToUse;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    从上面可以看出,如果InstantiationAwareBeanPostProcessor中的postProcessProperties和postProcessPropertyValues都返回空的时候,表示这个bean不需要设置属性,直接返回了,直接进入下一个阶段。

    来看一下postProcessProperties这个方法的定义:

    @Nullable
    default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)
        throws BeansException {
        return null;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    PropertyValues中保存了bean实例对象中所有属性值的设置,所以我们可以在这个这个方法中对PropertyValues值进行修改。

    这个方法有2个比较重要的实现类
    AutowiredAnnotationBeanPostProcessor在这个方法中对@Autowired、@Value标注的字段、方法注入值。
    CommonAnnotationBeanPostProcessor在这个方法中对@Resource标注的字段和方法注入值。

    Bean属性赋值阶段

    这个过程比较简单了,循环处理PropertyValues中的属性值信息,通过反射调用set方法将属性的值设置到bean实例中。

    PropertyValues中的值是通过bean xml中property元素配置的,或者调用MutablePropertyValues中add方法设置的值。

    阶段9:Bean初始化阶段

    这个阶段分为5个小的阶段

    • Bean Aware接口回调
    • Bean初始化前操作
    • Bean初始化操作
    • Bean初始化后操作
    • Bean初始化完成操作

    Bean Aware接口回调

    private void invokeAwareMethods(final String beanName, final Object bean) {
            if (bean instanceof Aware) {
                if (bean instanceof BeanNameAware) {
                    ((BeanNameAware) bean).setBeanName(beanName);
                }
                if (bean instanceof BeanClassLoaderAware) {
                    ClassLoader bcl = getBeanClassLoader();
                    if (bcl != null) {
                        ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
                    }
                }
                if (bean instanceof BeanFactoryAware) {
                    ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
                }
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    如果我们的bean实例实现了上面的接口,会按照下面的顺序依次进行调用:
    BeanNameAware:将bean的名称注入进去
    BeanClassLoaderAware:将BeanClassLoader注入进去
    BeanFactoryAware:将BeanFactory注入进去

    Bean初始化前操作

    @Override
    public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
        throws BeansException {
        Object result = existingBean;
        for (BeanPostProcessor processor : getBeanPostProcessors()) {
            Object current = processor.postProcessBeforeInitialization(result, beanName);
            if (current == null) {
                return result;
            }
            result = current;
        }
        return result;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    会调用BeanPostProcessor的postProcessBeforeInitialization方法,若返回null,当前方法将结束。
    通常称postProcessBeforeInitialization这个方法为:bean初始化前操作。
    这个接口有2个实现类,比较重要:

    org.springframework.context.support.ApplicationContextAwareProcessor
    org.springframework.context.annotation.CommonAnnotationBeanPostProcessor
    
    • 1
    • 2

    ApplicationContextAwareProcessor注入6个Aware接口对象
    如果bean实现了下面的接口,在ApplicationContextAwareProcessor#postProcessBeforeInitialization中会依次调用下面接口中的方法,将Aware前缀对应的对象注入到bean实例中。

    EnvironmentAware:注入Environment对象
    EmbeddedValueResolverAware:注入EmbeddedValueResolver对象
    ResourceLoaderAware:注入ResourceLoader对象
    ApplicationEventPublisherAware:注入ApplicationEventPublisher对象
    MessageSourceAware:注入MessageSource对象
    ApplicationContextAware:注入ApplicationContext对象

    从名称上可以看出这个类以ApplicationContext开头的,说明这个类只能在ApplicationContext环境中使用。

    CommonAnnotationBeanPostProcessor调用@PostConstruct标注的方法
    CommonAnnotationBeanPostProcessor#postProcessBeforeInitialization中会调用bean中所有标注@PostConstruct注解的方法

    Bean初始化阶段

    2个步骤

    • 调用InitializingBean接口的afterPropertiesSet方法
    • 调用定义bean的时候指定的初始化方法。
      调用InitializingBean接口的afterPropertiesSet方法
      来看一下InitializingBean这个接口
    public interface InitializingBean {
        void afterPropertiesSet() throws Exception;
    }
    
    • 1
    • 2
    • 3

    当我们的bean实现了这个接口的时候,会在这个阶段被调用

    调用bean定义的时候指定的初始化方法
    先来看一下如何指定bean的初始化方法,3种方式

    方式1:xml方式指定初始化方法

    <bean init-method="bean中方法名称"/>
    
    • 1

    方式2:@Bean的方式指定初始化方法

    @Bean(initMethod = "初始化的方法")
    
    • 1

    方式3:api的方式指定初始化方法

    this.beanDefinition.setInitMethodName(methodName);
    
    • 1

    初始化方法最终会赋值给下面这个字段

    org.springframework.beans.factory.support.AbstractBeanDefinition#initMethodName
    
    • 1

    Bean初始化后阶段

    @Override
    public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
        throws BeansException {
        Object result = existingBean;
        for (BeanPostProcessor processor : getBeanPostProcessors()) {
            Object current = processor.postProcessAfterInitialization(result, beanName);
            if (current == null) {
                return result;
            }
            result = current;
        }
        return result;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    调用BeanPostProcessor接口的postProcessAfterInitialization方法,返回null的时候,会中断上面的操作
    通常称postProcessAfterInitialization这个方法为:bean初始化后置操作。

    阶段10:所有单例bean初始化完成后阶段

    所有单例bean实例化完成之后,spring会回调下面这个接口:

    public interface SmartInitializingSingleton {
        void afterSingletonsInstantiated();
    }
    
    • 1
    • 2
    • 3

    调用逻辑在下面这个方法中

    /**
     * 确保所有非lazy的单例都被实例化,同时考虑到FactoryBeans。如果需要,通常在工厂设置结束时调用。
     */
    org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons
    
    • 1
    • 2
    • 3
    • 4

    这个方法内部会先触发所有非延迟加载的单例bean初始化,然后从容器中找到类型是SmartInitializingSingleton的bean,调用他们的afterSingletonsInstantiated方法。

    ApplicationContext的容器,内部最终都会调用上面这个方法触发所有单例bean的初始化。

    阶段11:Bean使用阶段

    阶段12:Bean销毁阶段

    触发bean销毁的几种方式

    • 调用org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#destroyBean
    • 调用org.springframework.beans.factory.config.ConfigurableBeanFactory#destroySingletons
    • 调用ApplicationContext中的close方法
      Bean销毁阶段会依次执行
    • 轮询beanPostProcessors列表,如果是DestructionAwareBeanPostProcessor这种类型的,会调用其内部的postProcessBeforeDestruction方法
    • 如果bean实现了org.springframework.beans.factory.DisposableBean接口,会调用这个接口中的destroy方法
    • 调用bean自定义的销毁方法

    DestructionAwareBeanPostProcessor接口

    public interface DestructionAwareBeanPostProcessor extends BeanPostProcessor {
        /**
         * bean销毁前调用的方法
         */
        void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException;
        /**
         * 用来判断bean是否需要触发postProcessBeforeDestruction方法
         */
        default boolean requiresDestruction(Object bean) {
            return true;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    这个接口有个关键的实现类:

    org.springframework.context.annotation.CommonAnnotationBeanPostProcessor
    CommonAnnotationBeanPostProcessor#postProcessBeforeDestruction方法中会调用bean中所有标注了@PreDestroy的方法。
    自定义销毁方法有3种方式

    方式1:xml中指定销毁方法

    <bean destroy-method="bean中方法名称"/>
    
    • 1

    方式2:@Bean中指定销毁方法

    @Bean(destroyMethod = "初始化的方法")
    
    • 1

    方式3:api的方式指定销毁方法

    this.beanDefinition.setDestroyMethodName(methodName);
    
    • 1

    初始化方法最终会赋值给下面这个字段

    org.springframework.beans.factory.support.AbstractBeanDefinition#destroyMethodName

    AbstractApplicationContext类(非常重要的类)
    在这里插入图片描述

    BeanFactory接口
    这个我们已经很熟悉了,Bean工厂的顶层接口

    DefaultListableBeanFactory类
    实现了BeanFactory接口,可以说这个可以是BeanFactory接口真正的唯一实现,内部真正实现了bean生命周期中的所有代码。

    其他的一些类都是依赖于DefaultListableBeanFactory类,将请求转发给DefaultListableBeanFactory进行bean的处理的。

    其他3个类
    我们经常用到的就是这3个类:AnnotationConfigApplicationContext/ClassPathXmlApplicationContext/FileSystemXmlApplicationContext这3个类,他们的主要内部的功能是依赖他的父类AbstractApplicationContext来实现的,所以大家主要看AbstractApplicationContext这个类。

    AbstractApplicationContext类
    这个类中有2个比较重要的方法

    public abstract ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException;
    protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory)
    
    • 1
    • 2

    大家是否注意过我们使用AnnotationConfigApplicationContext的时候,经常调用reflush方法,这个方法内部就会调用上面这2个方法。

    第一个方法:getBeanFactory()
    返回当前应用上下文中的ConfigurableListableBeanFactory,这也是个接口类型的,这个接口有一个唯一的实现类:DefaultListableBeanFactory。

    有没有很熟悉,上面说过:DefaultListableBeanFactory是BeanFactory真正的唯一实现。

    应用上线文中就会使用这个ConfigurableListableBeanFactory来操作spring容器。

    第二个方法:registerBeanPostProcessors
    说的通俗点:这个方法就是向ConfigurableListableBeanFactory中注册BeanPostProcessor,内容会从spring容器中获取所有类型的BeanPostProcessor,将其添加到DefaultListableBeanFactory#beanPostProcessors列表中

    看一下这个方法的源码:

    protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
        PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
    }
    
    • 1
    • 2
    • 3

    会将请求转发给PostProcessorRegistrationDelegate#registerBeanPostProcessors。

    内部比较长,大家可以去看一下源码,这个方法内部主要用到了4个BeanPostProcessor类型的List集合。

    List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
    List<BeanPostProcessor> orderedPostProcessors
    List<BeanPostProcessor> nonOrderedPostProcessors;
    List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
    
    • 1
    • 2
    • 3
    • 4

    先说一下:当到方法的时候,spring容器中已经完成了所有Bean的注册。

    spring会从容器中找出所有类型的BeanPostProcessor列表,然后按照下面的规则将其分别放到上面的4个集合中,上面4个集合中的BeanPostProcessor会被依次添加到DefaultListableBeanFactory#beanPostProcessors列表中,来看一下4个集合的分别放的是那些BeanPostProcessor:

    priorityOrderedPostProcessors(指定优先级的BeanPostProcessor)
    实现org.springframework.core.PriorityOrdered接口的BeanPostProcessor,但是不包含MergedBeanDefinitionPostProcessor类型的

    orderedPostProcessors(指定了顺序的BeanPostProcessor)
    实现了org.springframework.core.annotation.Order接口的BeanPostProcessor,但是不包含MergedBeanDefinitionPostProcessor类型的

    nonOrderedPostProcessors(未指定顺序的BeanPostProcessor)
    上面2种类型之外以及MergedBeanDefinitionPostProcessor之外的

    internalPostProcessors
    MergedBeanDefinitionPostProcessor类型的BeanPostProcessor列表。

    大家可以去看一下CommonAnnotationBeanPostProcessor和AutowiredAnnotationBeanPostProcessor,这两个类都实现了PriorityOrdered接口,但是他们也实现了MergedBeanDefinitionPostProcessor接口,所以最终他们会被丢到internalPostProcessors这个集合中,会被放入BeanPostProcessor的最后面。

    Bean生命周期流程图

    在这里插入图片描述

  • 相关阅读:
    APS生产排产实现家居行业的智能化排产
    PLSQL连接Oracle11g64位操作步骤
    优橙内推海南专场——5G网络优化(中高级)工程师
    JAVA基础之单元测试
    Java8接口之默认方法简介说明
    封装composer包
    Unable to access jarfile shop-0.0.3-SNAPSHOT.jar
    「学习笔记」字符串基础:Hash,KMP与Trie
    关于灭弧式智慧用电在养老机构的应用案例分析-安科瑞 蒋静
    陇萃堂:CRM系统赋能业务人员以及渠道商,线上线下快速突破和拓展
  • 原文地址:https://blog.csdn.net/ysj_2021/article/details/125610681