13.spring系列- bean生命周期-1

bean 生命周期13个环节

  1. 阶段1:bean元信息配置阶段
  2. 阶段2:bean元信息解析阶段
  3. 阶段3:将bean注册到容器中
  4. 阶段4:beanDefinition合并阶段
  5. 阶段5:bean class加载阶段
  6. 阶段6:bean 实例化阶段
    6.1:bean实例化前阶段
    6.2:bean实例化阶段
  7. 阶段7:合并后的beanDefinition处理
  8. 阶段8:属性赋值阶段
    8.1:bean实例化后阶段
    8.2:bean属性赋值前阶段
    8.3:bean属性赋值阶段
  9. 阶段9:bean初始化阶段
    9.1:bean aware 接口回调阶段
    9.2:bean 初始化前阶段
    9.3:bean 初始化阶段
    9.4:bean 初始化后阶段
  10. 阶段10:所有单例bean初始化完成后阶段
  11. 阶段11:bean的使用阶段
  12. 阶段12:bean销毁前阶段
  13. 阶段13:bean销毁阶段

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

Bean 信息定义4中方式

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

API方式

我们只说这种方式,因为其他几种方式最终都会采用这种方式来定义bean配置信息。Spring容器启动的过程中,会将Bean解析成Spring内部的BeanDefinition结构。

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

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

BeanDefinition是个接口,有几个实现类,看一下类图:
在这里插入图片描述BeanDefinition接口: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();

}

RootBeanDefinition类:表示根bean定义信息,通常bean中没有父bean的就使用这种表示
ChildBeanDefinition类:表示子bean定义信息,如果需要指定父bean的,可以使用ChildBeanDefinition来定义子bean的配置信息,里面有个parentName属性,用来指定父bean的名称。
GenericBeanDefinition类:通用的bean定义信息,既可以表示没有父bean的bean配置信息,也可以表示有父bean的子bean配置信息,这个类里面也有parentName属性,用来指定父bean的名称。

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

案例 :组装一个简单的bean

public class Car {
}
    @Test
    public void testCar(){
        BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.rootBeanDefinition(Car.class);
        AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();
        System.out.println(beanDefinition);
    }

运行结果:

Root bean: class [com.spring.beanLife.Car]; scope=; abstract=false; lazyInit=null; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null

案例:组装一个有属性的bean

public class Car {

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Car{" +
                "name='" + name + '\'' +
                '}';
    }
}
@Test
    public void testCar(){
        BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.rootBeanDefinition(Car.class);
        //添加属性
        beanDefinitionBuilder.addPropertyValue("name","Audi");
        AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();
        //创建spring容器
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        //把beanDefinition注册到容器中
        beanFactory.registerBeanDefinition("car",beanDefinition);
        Car bean = (Car) beanFactory.getBean("car");
        System.out.println(bean);
    }

运行结果:

Car{name='Audi'}

案例:组装一个有依赖关系的bean

两个类,一个car , 一个user .

public class Car {

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Car{" +
                "name='" + name + '\'' +
                '}';
    }
}
public class User {

    private Car car;

    @Override
    public String toString() {
        return "User{" +
                "car=" + car +
                '}';
    }

    public Car getCar() {
        return car;
    }

    public void setCar(Car car) {
        this.car = car;
    }
}

测试:

@Test
    public void testUserCar(){
        AbstractBeanDefinition carBeanDefinition = BeanDefinitionBuilder.rootBeanDefinition(Car.class)
                .addPropertyValue("name","Audi")
                .getBeanDefinition();
        AbstractBeanDefinition userBeanDefinition = BeanDefinitionBuilder.rootBeanDefinition(User.class)
                /**
                 * <bean id="car" class="xxx.Car">
                 *     <property name="name" value="奥迪"/>
                 * </bean>
                 *
                 * <bean id="user" class="xxx.User">
                 *     <property name="car" ref="car"/>
                 * </bean>
                 */
                .addPropertyReference("car","car")
                .getBeanDefinition();
        //创建spring容器
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        beanFactory.registerBeanDefinition("car",carBeanDefinition);
        beanFactory.registerBeanDefinition("user",userBeanDefinition);
        System.out.println(beanFactory.getBean("user"));
        System.out.println(beanFactory.getBean("car"));
    }

运行结果:

User{car=Car{name='Audi'}}
Car{name='Audi'}

小结

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进行测试:

    @Test
    public void testXmlRead(){
        //定义spring容器
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        //定义一个xml的BeanDefinition读取器
        XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
        //定义xml路径,然后读取
        String path = "";
        xmlBeanDefinitionReader.loadBeanDefinitions(path);
        //从容器中获取bean
        String[] beanDefinitionNames = beanFactory.getBeanDefinitionNames();
    }

注意:这种方式,获取的BeanDefinition都是GenericBeanDefinition这种类型的,也就是说xml中定义的bean被解析之后都是通过GenericBeanDefinition这种类型表示的。

properties文件定义bean的解析:PropertiesBeanDefinitionReader

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

@Test
    public void testProperties(){
        //定义spring容器
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        PropertiesBeanDefinitionReader definitionReader = new PropertiesBeanDefinitionReader(beanFactory);
        String path = "";
        definitionReader.loadBeanDefinitions(path);
        //从容器中获取bean
        String[] beanDefinitionNames = beanFactory.getBeanDefinitionNames();
    }

**注解方式:AnnotatedBeanDefinitionReader **

@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@Primary
@Lazy
public class Service1 {
}

public class Service2 {

    @Autowired
    Service1 service1;

    @Override
    public String toString() {
        return "Service2{" +
                "service1=" + service1 +
                '}';
    }
}
   @Test
    public void testAnn(){
        //定义spring容器
        DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
        AnnotatedBeanDefinitionReader definitionReader = new AnnotatedBeanDefinitionReader(factory);
        definitionReader.register(com.spring.beanLife.Service1.class, com.spring.beanLife.Service2.class);
        //打印出注册的bean的配置信息
        for (String beanName : new String[]{"service1", "service2"}) {
            //通过名称从容器中获取对应的BeanDefinition信息
            BeanDefinition beanDefinition = factory.getBeanDefinition(beanName);
            //获取BeanDefinition具体使用的是哪个类
            String beanDefinitionClassName = beanDefinition.getClass().getName();
            //通过名称获取bean对象
            Object bean = factory.getBean(beanName);
            //打印输出
            System.out.println(beanName + ":");
            System.out.println("    beanDefinitionClassName:" + beanDefinitionClassName);
            System.out.println("    beanDefinition:" + beanDefinition);
            System.out.println("    bean:" + bean);
        }
    }

输出结果:

service1:
    beanDefinitionClassName:org.springframework.beans.factory.annotation.AnnotatedGenericBeanDefinition
    beanDefinition:Generic bean: class [com.spring.beanLife.Service1]; scope=prototype; abstract=false; lazyInit=true; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=true; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null
    bean:com.spring.beanLife.Service1@24aed80c
14:13:35.579 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'service2'
service2:
    beanDefinitionClassName:org.springframework.beans.factory.annotation.AnnotatedGenericBeanDefinition
    beanDefinition:Generic bean: class [com.spring.beanLife.Service2]; scope=singleton; abstract=false; lazyInit=null; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null
    bean:Service2{service1=null}

输出中可以看出service1这个bean的beanDefinition中lazyInit确实为true,primary也为true,scope为prototype,说明类Service1注解上标注3个注解信息被解析之后放在了beanDefinition中。

注意下:最后一行中的service1为什么为null,不是标注了@Autowired么?大家先想下,随后我们在说。然后下个阶段:Bean注册

阶段3:Spring Bean注册阶段

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

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);

}

BeanDefinitionRegistry唯一实现:DefaultListableBeanFactory

我们经常用到的AnnotationConfigApplicationContext,但实际上其内部是转发给了DefaultListableBeanFactory进行处理的,所以真正实现这个接口的类是DefaultListableBeanFactory。

案例

@Test
    public void testBeanDefinitionRegistry() {
        //创建一个bean工厂,这个默认实现了BeanDefinitionRegistry接口,所以也是一个bean注册器
        DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
        //定义一个bean
        GenericBeanDefinition nameBdf = new GenericBeanDefinition();
        nameBdf.setBeanClass(String.class);
        nameBdf.getConstructorArgumentValues().addIndexedArgumentValue(0, "Java");
        //将bean注册到容器中
        factory.registerBeanDefinition("name", nameBdf);
        //通过名称获取BeanDefinition
        System.out.println(factory.getBeanDefinition("name"));
        //通过名称判断是否注册过BeanDefinition
        System.out.println(factory.containsBeanDefinition("name"));
        //获取所有注册的名称
        System.out.println(Arrays.asList(factory.getBeanDefinitionNames()));
        //获取已注册的BeanDefinition的数量
        System.out.println(factory.getBeanDefinitionCount());
        //判断指定的name是否使用过
        System.out.println(factory.isBeanNameInUse("name"));
        //别名相关方法
        //为name注册2个别名
        factory.registerAlias("name", "alias-name-1");
        factory.registerAlias("name", "alias-name-2");
        //判断alias-name-1是否已被作为别名使用
        System.out.println(factory.isAlias("alias-name-1"));
        //通过名称获取对应的所有别名
        System.out.println(Arrays.asList(factory.getAliases("name")));
        //最后我们再来获取一下这个bean
        System.out.println(factory.getBean("name"));
    }

下面要介绍的从阶段4到阶段14,也就是从:BeanDefinition合并阶段到Bean初始化完成阶段,都是在调用getBean从容器中获取bean对象的过程中发送的操作,要注意细看了,大家下去了建议去看getBean这个方法的源码,以下过程均来自于这个方法:

org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值