• Spring之bean的生命周期


    Spring之bean的生命周期

    在传统的Java应用中,bean的生命周期很简单,使用Java关键字 new 进行Bean 的实例化,然后该Bean 就能够使用了。一旦bean不再被使用,则由Java自动进行垃圾回收。

    相比之下,Spring管理Bean的生命周期就复杂多了,正确理解Bean 的生命周期非常重要,因为Spring对Bean的管理可扩展性非常强,下面展示了一个Bean的构造过程

    image

    1. Bean 容器找到配置文件中 Spring Bean 的定义。
    2. Bean 容器利用 Java Reflection API 创建一个 Bean 的实例。
    3. 如果涉及到一些属性值 利用 set()方法设置一些属性值。
    4. 如果实现了其他 *.Aware接口,就调用相应的方法。
    5. 如果有和加载这个 Bean 的 Spring 容器相关的 BeanPostProcessor 对象,执行postProcessBeforeInitialization() 方法
    6. 如果 Bean 实现了InitializingBean接口,执行afterPropertiesSet()方法。
    7. 如果 Bean 在配置文件中的定义包含 init-method 属性,执行指定的方法。
    8. 如果有和加载这个 Bean 的 Spring 容器相关的 BeanPostProcessor 对象,执行postProcessAfterInitialization() 方法
    9. 当要销毁 Bean 的时候,如果 Bean 实现了 DisposableBean 接口,执行 destroy() 方法。
    10. 当要销毁 Bean 的时候,如果 Bean 在配置文件中的定义包含 destroy-method 属性,执行指定的方法。

    BeanFactory 的注释里,有这么一段话,如下图所示:
    image

    代码演示

    1. 新建一个 User 类,让其实现接口 BeanNameAwareBeanFactoryAwareInitializingBeanDiposableBean 这4个接口,以及编写userInit()userDestroy() 两个方法,对应配置文件中 init-methoddestroy-method
    package com.wqing.domain;
    
    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.*;
    
    /**
     * @Description 用于演示 Bean 的生命周期
     * @Author wqing
     * @Date 2022/8/11 15:37
     */
    public class User implements BeanNameAware, BeanFactoryAware,
            InitializingBean, DisposableBean {
        private String name;
        private Integer age;
    
        private BeanFactory beanFactory;
        private String beanName;
    
        public User() {
            System.out.println("[构造器]--调用Person的构造函数进行实例化");
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            System.out.println("[属性填充]--注入属性name");
            this.name = name;
        }
    
        public Integer getAge() {
            return age;
        }
    
        public void setAge(Integer age) {
            System.out.println("[属性填充]--注入属性age");
            this.age = age;
        }
    
        @Override
        public String toString() {
            return "User{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    
        //这是 BeanFactoryAware 接口的方法
        @Override
        public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
            System.out.println("[BeanFactoryAware]--执行BeanFactoryAware.setBeanFactory(),beanFactory为:" + beanFactory);
            this.beanFactory = beanFactory;
        }
    
        //这是 BeanNameAware 接口的方法
        @Override
        public void setBeanName(String name) {
            System.out.println("[BeanNameAware]--执行BeanNameAware.setBeanName(),beanName为: " + name);
            this.beanName = name;
        }
    
        //这是 DisposableBean 接口的方法
        @Override
        public void destroy() throws Exception {
            System.out.println("[DisposableBean]--执行DisposableBean.destroy()");
        }
    
        //这是 InitializingBean 接口的方法
        @Override
        public void afterPropertiesSet() throws Exception {
            System.out.println("[InitializingBean]--执行InitializingBean.afterPropertiesSet()");
        }
    
        // 通过的init-method属性指定的初始化方法
        public void userInit() {
            System.out.println("[init-method]--执行的init-method属性指定的初始化方法");
        }
    
        // 通过的destroy-method属性指定的初始化方法
        public void userDestroy() {
            System.out.println("[destroy-method]--执行的destroy-method属性指定的销毁方法");
        }
    }
    
    
    1. 自定义 MyBeanPostProcessor 实现 BeanPostProcessor
    package com.wqing.domain;
    
    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.config.BeanPostProcessor;
    
    /**
     * @Description
     * @Author 王清
     * @Date 2022/8/11 16:06
     */
    public class MyBeanPostProcessor implements BeanPostProcessor {
        /**
         * 实例化、依赖注入完毕,在调用显示的初始化之前完成一些定制的初始化任务
         */
        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            System.out.println("[BeanPostProcessor]--执行BeanPostProcessor.postProcessBeforeInitialization()");
            return bean;
        }
    
        /**
         * 实例化、依赖注入、初始化完毕时执行
         */
        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            System.out.println("[BeanPostProcessor]--执行BeanPostProcessor.postProcessAfterInitialization()");
            return bean;
        }
    }
    

    BeanPostProcessor 接口包括2个方法 postProcessAfterInitializationpostProcessBeforeInitialization,这两个方法的第一个参数都是要处理的Bean对象,第二个参数都是Bean的name。返回值也都是要处理的Bean对象。

    1. 编写 application.xml,将 UserMyBeanPostProcessor 注册进容器
    
    <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="user" class="com.wqing.domain.User" init-method="userInit"
              destroy-method="userDestroy">
            <property name="name" value="张三"/>
            <property name="age" value="20"/>
        bean>
    
        <bean id="myBeanPostProcessor" class="com.wqing.domain.MyBeanPostProcessor"/>
    beans>
    
    1. 编写测试类
    package com.wqing;
    
    import com.wqing.domain.User;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    /**
     * @Description
     * @Author wqing
     * @Date 2022/8/5 14:38
     */
    public class Test {
        public static void main(String[] args) {
            System.out.println("容器开始创建");
            ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
            User bean = context.getBean(User.class);
            System.out.println("使用 bean");
            System.out.println(bean);
            System.out.println("容器开始销毁");
            context.close();
        }
    }
    

    执行结果

    容器开始创建
    [构造器]--调用Person的构造函数进行实例化
    [属性填充]--注入属性name
    [属性填充]--注入属性age
    [BeanNameAware]--执行BeanNameAware.setBeanName(),beanName为: user
    [BeanFactoryAware]--执行BeanFactoryAware.setBeanFactory(),beanFactory为:org.springframework.beans.factory.support.DefaultListableBeanFactory@38082d64: defining beans [user,myBeanPostProcessor]; root of factory hierarchy
    [BeanPostProcessor]--执行BeanPostProcessor.postProcessBeforeInitialization()
    [InitializingBean]--执行InitializingBean.afterPropertiesSet()
    [init-method]--执行的init-method属性指定的初始化方法
    [BeanPostProcessor]--执行BeanPostProcessor.postProcessAfterInitialization()
    使用 bean
    User{name='张三', age=20}
    容器开始销毁
    [DisposableBean]--执行DisposableBean.destroy()
    [destroy-method]--执行的destroy-method属性指定的销毁方法
    
  • 相关阅读:
    git@github.com: Permission denied (publickey).
    极空间变身监控录像机,搭配Onvif摄像头,实现实时观看和录制视频回放功能
    5个实用的WhatsApp 群发消息模板推荐!
    C语言实现单链表
    react路由根据用户角色设置权限校验
    Python内置函数系统学习(3)——数据转换与计算 (详细语法参考+参数说明+具体示例) 详解min()函数在列表、元组、字典的综合应用 | lambda 很牛哦!你怎么看!?
    基于微信小程序的线上课堂系统
    探花交友_第6章_圈子互动(新版)
    计算机硕士研究生毕设选题方向推荐 - 题目推荐
    设计模式-行为型模式-观察者模式
  • 原文地址:https://www.cnblogs.com/wqstart/p/16576851.html