05-Spring中Bean的生命周期

Bean的生命周期

生命周期就是对象从创建开始到最终销毁的整个过程 , Spring其实就是一个管理Bean对象的工厂,它负责对象的创建和销毁等

  • Bean生命周期的管理可以参考Spring的源码:AbstractAutowireCapableBeanFactory类的doCreateBean()方法

  • 研究生命周期的意义:在哪个时间节点上调用了哪个类的哪个方法,把需要在某个特殊的时间点上执行的一段代码放到对应节点上,然后到点会自动被调用

Bean的生命周期之五步

第一步:实例化Bean(调用无参数构造方法)

第二步:给Bean属性赋值(调用set方法)

第三步:初始化Bean(会调用Bean的init方法, 这个init方法需要自己写,并且在配置文件中需要使用init-method属性指定)

第四步:使用Bean

第五步:销毁Bean(会调用Bean的destroy方法, 这个destroy方法需要自己写,并且在配置文件中需要使用destroy-method属性指定)

  • 只有手动关闭Spring容器, bean的销毁方法才会被调用,需要向下转型执行ClassPathXmlApplicationContext特有的close方法
    在这里插入图片描述

定义一个Bean

public class User {
    private String name;

    public User() {
        System.out.println("1.实例化Bean");
    }

    public void setName(String name) {
        this.name = name;
        System.out.println("2.Bean属性赋值");
    }
	//配置bean的初始化方法
    public void initBean(){
        System.out.println("3.初始化Bean");
    }
	//配置bean的销毁方法
    public void destroyBean(){
        System.out.println("5.销毁Bean");
    }
}

编写spring的配置文件: init-method属性指定初始化方法名, destroy-method属性指定销毁方法名


<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.xsd">
    
    <bean id="userBean" class="com.powernode.spring6.bean.User" init-method="initBean" destroy-method="destroyBean">
        <property name="name" value="zhangsan"/>
    bean>
beans>

测试结果的执行顺序: 1.实例化Bean-->2.Bean属性赋值-->3.初始化Bean-->4.使用Bean-->5.销毁Bean

public class BeanLifecycleTest {
    @Test
    public void testLifecycle(){
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
        //以下这行代码执行了1.实例化Bean-->2.Bean属性赋值-->3.初始化Bean
        User userBean = applicationContext.getBean("userBean", User.class);
        System.out.println("4.使用Bean");
        // 必须手动关闭Spring容器才会销毁Bean从而执行Bean的销毁方法
        ClassPathXmlApplicationContext context = (ClassPathXmlApplicationContext) applicationContext;
        context.close();
    }
}

Bean生命周期之七步(掌握)

如果你还想在besn的初始化前和初始化后添加代码,需要加入Bean后处理器(编写一个类实现BeanPostProcessor接口并且实现before和after方法)

  • Bean后处理器将作用于整个配置文件中所有的bean

在这里插入图片描述

编写日志的Bean后处理器实现BeanPostProcessor接口并实现postProcessBeforeInitialization和postProcessAfterInitialization方法

  • 这两个方法都有两个参数:第一个参数是刚创建的bean对象, 第二个参数是bean的名字
public class LogBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("Bean后处理器的before方法执行,即将开始初始化");
        return bean;
    }
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("Bean后处理器的after方法执行,已完成初始化");
        return bean;
    }
}

在spring的配置文件中配置Bean后处理器(作用于当前配置文件中所有的Bean),并手动指定Bean的初始化方法和销毁方法


<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.xsd">    
    
    <bean class="com.powernode.spring6.bean.LogBeanPostProcessor"/>
    
    
    <bean id="userBean" class="com.powernode.spring6.bean.User" init-method="initBean" destroy-method="destroyBean">
        <property name="name" value="zhangsan"/>
    bean>
beans>

测试结果: 1.实例化Bean–>2.Bean属性赋值–>Bean后处理器的before方法–>3.初始化Bean–>Bean后处理器的after方法–>4.使用Bean–>5.销毁Bean

public class BeanLifecycleTest {
    @Test
    public void testLifecycle(){
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
        // 以下这行代码执行了1.实例化Bean-->2.Bean属性赋值-->Bean后处理器的before方法-->3.初始化Bean-->Bean后处理器的after方法
        User userBean = applicationContext.getBean("userBean", User.class);
        System.out.println("4.使用Bean");
        // 必须手动关闭Spring容器才会销毁Bean从而执行Bean的销毁方法
        ClassPathXmlApplicationContext context = (ClassPathXmlApplicationContext) applicationContext;
        context.close();
    }
}

Bean生命周期之十步(了解)

多添加了三个点位用来检查你这个Bean是否实现了某些特定的接口,如果实现了这些接口则Spring容器会调用这些接口中的方法

  • 调用这些接口中的方法目的是为了给你传递一些数据,让你更加方便使用

点位1:在Bean后处理器的before方法之前(检查Bean是否实现了Aware相关的接口BeanNameAware、BeanClassLoaderAware、BeanFactoryAware)

  • 当Bean实现了BeanNameAware,Spring会将Bean的名字传递给Bean
  • 当Bean实现了BeanClassLoaderAware,Spring会将加载该Bean的类加载器传递给Bean
  • 当Bean实现了BeanFactoryAware,Spring会将Bean工厂对象传递给Bean

点位2:在Bean后处理器的before方法之后(检查Bean是否实现了InitializingBean接口)

点位3:使用Bean之后或者说销毁Bean之前(检查Bean是否实现了DisposableBean接口)

05-Spring中Bean的生命周期_第1张图片

User类实现了BeanNameAware, BeanClassLoaderAware, BeanFactoryAware, InitializingBean, DisposableBean5个接口并实现它们的所有方法

  • InitializingBean接口的afterPropertiesSet方法早于init-method的执行 , DisposableBean接口的destroy方法早于destroy-method的执行
public class User implements BeanNameAware, BeanClassLoaderAware, BeanFactoryAware, InitializingBean, DisposableBean {
    private String name;

    public User() {
        System.out.println("1.实例化Bean");
    }

    public void setName(String name) {
        this.name = name;
        System.out.println("2.Bean属性赋值");
    }

    public void initBean(){
        System.out.println("6.初始化Bean");
    }

    public void destroyBean(){
        System.out.println("10.销毁Bean");
    }

    @Override
    public void setBeanClassLoader(ClassLoader classLoader) {
        System.out.println("3.类加载器:" + classLoader);
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("3.Bean工厂:" + beanFactory);
    }

    @Override
    public void setBeanName(String name) {
        System.out.println("3.bean名字:" + name);
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("9.DisposableBean destroy");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("5.afterPropertiesSet执行");
    }
}

编写Bean后处理器重写postProcessBeforeInitialization和postProcessAfterInitialization方法

public class LogBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("4.Bean后处理器的before方法执行,即将开始初始化");
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("7.Bean后处理器的after方法执行,已完成初始化");
        return bean;
    }
}

在spring的配置文件中配置Bean后处理器(作用于当前配置文件中所有的Bean),并手动指定Bean的初始化方法和销毁方法


<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.xsd">    
    
    <bean class="com.powernode.spring6.bean.LogBeanPostProcessor"/>
    
    
    <bean id="userBean" class="com.powernode.spring6.bean.User" init-method="initBean" destroy-method="destroyBean">
        <property name="name" value="zhangsan"/>
    bean>
beans>

测试结果

public class BeanLifecycleTest {
    @Test
    public void testLifecycle(){
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
        User userBean = applicationContext.getBean("userBean", User.class);
        System.out.println("8.使用Bean");
        // 必须手动关闭Spring容器才会销毁Bean从而执行Bean的销毁方法
        ClassPathXmlApplicationContext context = (ClassPathXmlApplicationContext) applicationContext;
        context.close();
    }
}

05-Spring中Bean的生命周期_第2张图片

Bean的不同管理方式

Spring容器根据Bean的作用域来选择管理方式

  • 对于singleton作用域的Bean: Spring能够精确地知道该Bean何时被创建,何时初始化完成以及何时被销毁(完整的生命周期)
  • 对于prototype作用域的Bean: Spring只负责Bean的创建, 当客户端程序获取到该Bean后,Spring容器将不再跟踪其生命周期 , 剩下的操作交给客户端管理

将spring配置文件中User类的scope属性设置为prototype


<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.xsd">
	
    <bean id="userBean" class="com.powernode.spring6.bean.User" init-method="initBean" destroy-method="destroyBean" scope="prototype">
        <property name="name" value="zhangsan"/>
    bean>
    
    <bean class="com.powernode.spring6.bean.LogBeanPostProcessor"/>
beans>
public class BeanLifecycleTest {
    @Test
    public void testLifecycle(){
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
        User userBean = applicationContext.getBean("userBean", User.class);
        System.out.println("8.使用Bean");
        // 当客户端程序获取到该Bean后,容器将不再跟踪其生命周期即生命周期方法不再执行,剩下的操作交给客户端管理
        ClassPathXmlApplicationContext context = (ClassPathXmlApplicationContext) applicationContext;
        context.close();
    }
}

05-Spring中Bean的生命周期_第3张图片

Spring管理自己new的对象

有些时候可能会需要将我们自己new的java对象交给Spring容器管理,此时需要创建默认的DefaultListableBeanFactory工厂对象用来注册Bean并指定Bean的id

// 定义Bean
public class User {
}
public class RegisterBeanTest {
    @Test
    public void testBeanRegister(){
        // 自己new的User对象
        User user = new User();
        // com.powernode.spring6.bean.User@79e2c065
        System.out.println(user);

        // 创建默认列表BeanFactory对象注册Bean
        DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
        // 注册Bean
        factory.registerSingleton("userBean", user);
        // 根据id从spring容器中获取bean
        User userBean = factory.getBean("userBean", User.class);
        // com.powernode.spring6.bean.User@79e2c065
        System.out.println(userBean);
    }
}

你可能感兴趣的:(Bean,spring,java,数据库,Bean的生命周期)