程序员最近都爱上了这个网站  程序员们快来瞅瞅吧!  it98k网:it98k.com

本站消息

站长简介/公众号

  出租广告位,需要合作请联系站长


+关注
已关注

分类  

暂无分类

标签  

暂无标签

日期归档  

SpringBean的生命周期

发布于2021-06-12 13:59     阅读(271)     评论(0)     点赞(26)     收藏(3)


你未必出类拔萃,但一定与众不同

SpringBean的生命周期

Spring IoC的本质就是为了管理Bean

在这里插入图片描述

生命周期

  • Bean 容器找到配置⽂件中 Spring Bean 的定义。

  • Bean 容器利⽤反射创建⼀个Bean的实例。

  • 如果涉及到⼀些属性值 利⽤ set() ⽅法设置⼀些属性值。

  • 如果Bean 实现了接口BeanNameAware的setBeanName方法,那么就会调用这个方法。

  • 如果Bean实现了接口BeanFactoryAware的setBeanFactory方法,那么就会调用这个方法。

  • 如果Bean实现了接口AppicationContextAware的setAppicationContext方法,且这个Spring IoC容器必须是一个AppicationContext接口的实现类,那么就会调用这个方法,否则不调用

  • 如果Bean 实现了接口BeanPostProcessor的postProcessBeforeInitialization方法那么就会调用这个方法。

  • 如果Bean实现了接口BeanFactoryPostProcessor的afterPropertiesSet方法,那么就会调用这个方法

  • 如果Bean自定义了初始化方法,它就会调用已定义的初始化方法

  • 如果Bean实现了接口BeanPostProcessor的postProcessAfterInitialization方法,完成了这些调用,这个时候Bean就完成了初始化,那么Bean就生存在了Spring IoC的容器中。

    当服务器正常关闭或者其他关闭Spring IoC容器的事件,就会完成对Bean的销毁

  • 如果Bean实现了接口DisPosableBean的destory方法,那么就会调用它。

  • 如果定义了自定义的销毁方法,那么就会调用它。

现在我们来看看一个简易的bean的实现 了解一个大概实例化初始化流程

先写一个实体类

去实现BeanFactoryAware, BeanNameAware, InitializingBean, DisposableBean这些接口

public class Student implements BeanFactoryAware, BeanNameAware,
        InitializingBean, DisposableBean {

    private String studentName;
    private String studentAddress;
    private String studentPhone;

    private BeanFactory beanFactory;

    private String beanName;

    public String getStudentName() {
        return studentName;
    }

    public void setStudentName(String studentName) {
        System.out.println("---注入属性 studentName-----");
        this.studentName = studentName;
    }

    public String getStudentAddress() {
        return studentAddress;
    }

    public void setStudentAddress(String studentAddress) {
        System.out.println("---注入属性 StudentAddress-----");
        this.studentAddress = studentAddress;
    }

    public String getStudentPhone() {
        return studentPhone;
    }

    public void setStudentPhone(String studentPhone) {
        System.out.println("---注入属性 studentPhone-----");
        this.studentPhone = studentPhone;
    }

    // 这是BeanFactoryAware接口方法
    @Override
    public void setBeanFactory(BeanFactory arg0) throws BeansException {
        System.out.println("----BeanFactoryAware接口----调用BeanFactoryAware.setBeanFactory()");
        this.beanFactory = arg0;
    }

    // 这是BeanNameAware接口方法
    @Override
    public void setBeanName(String arg0) {
        System.out.println("----BeanNameAware接口----调用BeanNameAware.setBeanName()");
        this.beanName = arg0;
    }

    // 这是InitializingBean接口方法
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("----InitializingBean接口----调用InitializingBean.afterPropertiesSet()");
    }

    // 这是DiposibleBean接口方法
    @Override
    public void destroy() throws Exception {
        System.out.println("----DiposibleBean接口----调用DiposibleBean.destory()");
    }

    // 通过<bean>的init-method属性指定的初始化方法
    public void myInit() {
        System.out.println("---init-method---调用<bean>的init-method属性指定的初始化方法");
    }

    // 通过<bean>的destroy-method属性指定的初始化方法
    public void myDestroy() {
        System.out.println("---destroy-method---调用<bean>的destroy-method属性指定的初始化方法");
    }
}

编写spring配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="beanPostProcessor" class="com.wyyy.run.test.MyBeanPostProcessor">
    </bean>

    <bean id="instantiationAwareBeanPostProcessor" class="com.wyyy.run.test.MyInstantiationAwareBeanPostProcessor">
    </bean>

    <bean id="beanFactoryPostProcessor" class="com.wyyy.run.test.MyBeanFactoryPostProcessor">
    </bean>

    <bean id="student" class="com.wyyy.run.test.Student" init-method="myInit"
          destroy-method="myDestroy" scope="singleton" p:studentName="张三" p:studentAddress="广州"
          p:studentPhone= "15900000000" />
</beans>

如果Bean 实现了接口BeanNameAware的setBeanName方法,那么就会调用这个方法。

如果Bean实现了接口BeanFactoryAware的setBeanFactory方法,那么就会调用这个方法。

这里我们的bean就实现了这个两个接口,因此会调用这个方法,还在实例化之前

BeanPostProcessor 前置处理器

BeanPostProcessor是Spring IOC容器给我们提供的一个扩展接口

public interface BeanPostProcessor {
    //bean初始化方法调用前被调用
    Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
    //bean初始化方法调用后被调用
    Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}

我们现在自定义一个MyBeanPostProcessor去实现这个接口 监测这个接口方法的初始化顺序

public class MyBeanPostProcessor implements BeanPostProcessor {

    public MyBeanPostProcessor() {
        super();
        System.out.println("BeanPostProcessor构造器");
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName)
            throws BeansException {
        System.out.println("postProcessAfterInitialization");
        return bean;
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName)
            throws BeansException {
        System.out.println("postProcessBeforeInitialization");
        return bean;
    }
}

BeanFactoryPostProcessor

BeanFactoryPostProcessor是在spring容器加载了bean的定义文件之后,在bean实例化之前执行的

实现该接口,可以在spring的bean创建之前,修改bean的定义属性。也就是说,Spring允许BeanFactoryPostProcessor在容器实例化任何其它bean之前读取配置元数据,并可以进行修改,例如可以把bean的scope从singleton改为prototype,也可以把property的值给修改掉。可以同时配置多个BeanFactoryPostProcessor,并通过设置’order’属性来控制各个BeanFactoryPostProcessor的执行次序。

@FunctionalInterface
public interface BeanFactoryPostProcessor {
    void postProcessBeanFactory(ConfigurableListableBeanFactory var1) throws BeansException;
}

ConfigurableListableBeanFactory作为参数可以获取到bean的一些定义信息

我们自定义一个MyBeanFactoryPostProcessor

public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

    public MyBeanFactoryPostProcessor() {
        super();
        System.out.println("BeanFactoryPostProcessor构造器");
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory var1)
            throws BeansException {
        System.out.println("postProcessBeanFactory");
        BeanDefinition bd = var1.getBeanDefinition("student");
        bd.getPropertyValues().addPropertyValue("studentPhone", "110");
    }

}

BeanDefinition

Spring容器启动的过程中,会将Bean解析成Spring内部的BeanDefinition结构

一个 BeanDefinition 描述了一个 Bean 实例,实例包含属性值、构造方法参数值以及更多实现信息。

public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
	//单例和原型
    String SCOPE_SINGLETON = "singleton";
    String SCOPE_PROTOTYPE = "prototype";
    //标识 Bean 的类别,分别对应 用户定义的 Bean、来源于配置文件的 Bean、Spring 内部的 Bean
    int ROLE_APPLICATION = 0;
    int ROLE_SUPPORT = 1;
    int ROLE_INFRASTRUCTURE = 2;
	//Bean 的父类名称
    void setParentName(@Nullable String var1);
    ......
}

BeanDefinition 描述了一个 Bean 的定义,实际上就是对象在容器中的抽象。通过这个 BeanDefinition 定义的数据结构,容器能够方便地对 Bean 进行管理。对于单例的 Bean,在第一次 getBean 的时候读取 BeanDefinition 获取定义,然后再创建和初始化 Bean,并缓存起来。对于原型的 Bean,在每一次 getBean 的时候都需要使用 BeanDefinition 的数据进行创建和初始化,不会缓存 Bean。

BeanDefinition 在 Spring 内部使用,外部开发者一般感知不到 BeanDefinition 的存在。我们使用时只需要关注通过 xml、注解怎样定义了一个 Bean,然后使用即可。而这中间的解析、创建、初始化都通过 BeanDefinition 来承载。

InstantiationAwareBeanPostProcessor

InstantiationAwareBeanPostProcessor代表了Spring的另外一段生命周期:实例化。先区别一下Spring Bean的实例化和初始化两个阶段的主要作用:

1、实例化的过程是一个创建Bean的过程,即调用Bean的构造函数,单例的Bean放入单例池中

2、初始化的过程是一个赋值的过程,即调用Bean的setter,设置Bean的属性

Instantiation表示实例化:实例化的意思在对象还未生成

Initialization表示初始化:初始化的意思在对象已经生成

自定义一个MyInstantiationAwareBeanPostProcessor类继承InstantiationAwareBeanPostProcessor重写两个方法

public class MyInstantiationAwareBeanPostProcessor extends
        InstantiationAwareBeanPostProcessorAdapter {

    public MyInstantiationAwareBeanPostProcessor() {
        super();
        System.out.println("这是InstantiationAwareBeanPostProcessorAdapter实现类构造器!!");
    }


    /**
     * 接口方法、实例化Bean之前调用
     * @param beanClass
     * @param beanName
     * @return
     * @throws BeansException
     */
    @Override
    public Object postProcessBeforeInstantiation(Class beanClass,
                                                 String beanName) throws BeansException {
        System.out.println("InstantiationAwareBeanPostProcessor调用postProcessBeforeInstantiation方法");
        return null;
    }

    /**
     * 接口方法、实例化Bean之后调用
     * @param bean
     * @param beanName
     * @return
     * @throws BeansException
     */
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName)
            throws BeansException {
        System.out.println("InstantiationAwareBeanPostProcessor调用postProcessAfterInitialization方法");
        return bean;
    }

}

写个主函数进行测试

public static void main(String[] args) {
    System.out.println("初始化容器");
    ApplicationContext factory = new ClassPathXmlApplicationContext("spring-config.xml");
    System.out.println("容器初始化成功");
    Student student = factory.getBean("student",Student.class);
    System.out.println(student);
}

打印结果

初始化容器
BeanFactoryPostProcessor构造器
postProcessBeanFactory
BeanPostProcessor构造器
这是InstantiationAwareBeanPostProcessorAdapter实现类构造器!!
InstantiationAwareBeanPostProcessor调用postProcessBeforeInstantiation方法
---注入属性 StudentAddress-----
---注入属性 studentName-----
---注入属性 studentPhone-----
----BeanNameAware接口----调用BeanNameAware.setBeanName()
----BeanFactoryAware接口----调用BeanFactoryAware.setBeanFactory()
postProcessBeforeInitialization
----InitializingBean接口----调用InitializingBean.afterPropertiesSet()
---init-method---调用<bean>的init-method属性指定的初始化方法
postProcessAfterInitialization
InstantiationAwareBeanPostProcessor调用postProcessAfterInitialization方法
容器初始化成功
com.wyyy.run.test.Student@489115ef

原文链接:https://blog.csdn.net/qq_44752800/article/details/117729363



所属网站分类: 技术文章 > 博客

作者:狗蛋来了

链接:http://www.javaheidong.com/blog/article/222312/c393ed98149be8c52c1e/

来源:java黑洞网

任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任

26 0
收藏该文
已收藏

评论内容:(最多支持255个字符)