Spring Bean的生命周期验证

Spring容器的启动过程分为两个大的阶段:

  1. BeanDefinition的扫描
  2. 执行Bean的生命周期:实例化、属性填充、初始化过程、使用、销毁。另外,可以在初始化阶段用Aware接口和BeanPostProcessor做扩展。

下面我们通过代码验证第二个过程-Bean的生命周期:

实体类

Role

java 复制代码
public class Role {
    String roleName;

    public String getRoleName() {
        return roleName;
    }

    public void setRoleName(String roleName) {
        this.roleName = roleName;
    }
}

Role类将作为LifeCycleBean的依赖的实现类。

LifeCycleBean

定义Bean生命周期验证的具体实现类。

java 复制代码
public class LifeCycleBean implements InitializingBean, DisposableBean, ApplicationContextAware, BeanNameAware {

    /**
     * 模拟普通属性的注入
     */
    Integer age;

    /**
     * 模拟成员属性的注入
     */
    Role role;

    public LifeCycleBean() {
        System.out.println(String.format("%s实例化完成", getClass().getSimpleName()));
    }

    /**
     * 通过@PostConstruct调用初始化方法
     */
    @PostConstruct
    public void postConstruct() {
        System.out.println(String.format("%s的postConstruct()被调用", getClass().getSimpleName()));
    }

    /**
     * 通过实现InitializingBean初始化
     *
     * @throws Exception
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println(String.format("%s的afterPropertiesSet()被调用", getClass().getSimpleName()));
    }

    /**
     * 通过XML中的init-method,初始化Bean
     */
    public void initMethod() {
        System.out.println(String.format("%s的initMethod()被调用", getClass().getSimpleName()));
    }

    /**
     * 通过@PreDestroy指定销毁方法
     */
    @PreDestroy
    public void preDestroy() {
        System.out.println(String.format("%s的preDestroy()被调用", getClass().getSimpleName()));
    }

    /**
     * 通过Disposable接口实现销毁方法
     *
     * @throws Exception
     */
    @Override
    public void destroy() throws Exception {
        System.out.println(String.format("%s的destroy()被调用", getClass().getSimpleName()));
    }

    /**
     * 通过XML中,destroy-method指定销毁方法
     */
    public void destroyMethod() {
        System.out.println(String.format("%s的destroyMethod()被调用", getClass().getSimpleName()));
    }

    /**
     * 实现ApplicationContextAware接口
     *
     * @param applicationContext
     * @throws BeansException
     */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println(String.format("%s的setApplicationContext()被调用", getClass().getSimpleName()));
    }

    /**
     * 实现BeanNameAware接口
     *
     * @param name
     */
    @Override
    public void setBeanName(String name) {
        System.out.println(String.format("%s的setBeanName()被调用", getClass().getSimpleName()));
    }

    public void doSomething() {
        System.out.println(String.format("%s正在运行", getClass().getSimpleName()));
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        System.out.println(String.format("%s的属性age被设置", getClass().getSimpleName()));
        this.age = age;
    }

    public Role getRole() {
        return role;
    }

    public void setRole(Role role) {
        System.out.println(String.format("%s的属性role被设置", getClass().getSimpleName()));
        this.role = role;
    }
}
  • 实例化:即对应的构造函数
  • 属性填充:agerole两个属性用于验证属性填充过程,age为基本数据类型,role为引用类型
  • 初始化:实现InitializingBean接口,@PostConstruct注释的postConstruct()方法都是初始化流程;另外initMethod()也是初始化方法,稍后由XML配置文件定义。
  • Aware接口:ApplicationContextAwareBeanNameAware为Aware接口,用于初始化之前的扩展
  • 使用:doSomething()表示Bean初始化完毕后的使用
  • 销毁方法:实现DisposableBean接口、@PreDestroy注释的preDestroy()方法都是销毁流程;另外,destroyMethod()也是销毁方法,稍后由XML配置文件定义。

BeanPostProcessor

java 复制代码
public class MyBeanPostProcessor implements BeanPostProcessor {
    /**
     * Bean初始化前被调用
     * @param bean
     * @param beanName
     * @return
     * @throws BeansException
     */
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if(bean instanceof LifeCycleBean){
            System.out.println(String.format("Bean:%s,初始化之前调用BeanPostProcessor",beanName));
        }
        return bean;
    }

    /**
     * 初始化之后被调用
     * @param bean
     * @param beanName
     * @return
     * @throws BeansException
     */
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if(bean instanceof LifeCycleBean){
            System.out.println(String.format("Bean:%s,初始化之后调用BeanPostProcessor",beanName));
        }
        return bean;
    }
}

XML配置文件

lefeCycle.xml

xml 复制代码
<?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:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 开启注解方式 -->
    <!-- 开启后,@PostConstruct和@PreDestroy才能生效   -->
    <context:annotation-config/>

    <!-- 注册BeanPostProcessor -->
    <bean id="myBeanPostProcessor" class="com.ldh.processors.MyBeanPostProcessor"/>

    <!-- 注册Bean -->
    <bean id="role" class="com.ldh.entity.Role"/>
    <bean id="lifeCycleBean" class="com.ldh.entity.LifeCycleBean" init-method="initMethod" destroy-method="destroyMethod">
        <!-- 属性填充 -->
        <property name="age" value="18"/>
        <property name="role" ref="role"/>
    </bean>

</beans>
  • myBeanPostProcessor:注册MyBeanPostProcessor的Bean
  • role:注册Role的Bean,用于属性填充到lifeCycleBean
  • lifeCycleBean:注册LifeCycleBean的Bean;init-method用于指定初始化方法initMethod()destroy-method用于指定销毁方法destroyMethod()

测试代码

java 复制代码
@Test
public void lifeCycleTest(){
    ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("lifeCycle.xml");
    LifeCycleBean lifeCycleBean = applicationContext.getBean(LifeCycleBean.class);
    //使用Bean
    lifeCycleBean.doSomething();
    //关闭容器
    applicationContext.close();
}

测试结果

shell 复制代码
# 实例化
LifeCycleBean实例化完成
# 属性填充
LifeCycleBean的属性age被设置
LifeCycleBean的属性role被设置
# Aware接口调用
LifeCycleBean的setBeanName()被调用
LifeCycleBean的setApplicationContext()被调用
# 初始化前调用BeanPostProcessor
Bean:lifeCycleBean,初始化之前调用BeanPostProcessor
# 初始化
LifeCycleBean的postConstruct()被调用
LifeCycleBean的afterPropertiesSet()被调用
LifeCycleBean的initMethod()被调用
# 初始化后调用BeanPostProcessor
Bean:lifeCycleBean,初始化之后调用BeanPostProcessor
# 使用Bean
LifeCycleBean正在运行
# 销毁Bean
LifeCycleBean的preDestroy()被调用
LifeCycleBean的destroy()被调用
LifeCycleBean的destroyMethod()被调用
相关推荐
IDRSolutions_CN19 分钟前
PDF 转 HTML5 —— HTML5 填充图形不支持 Even-Odd 奇偶规则?(第二部分)
java·经验分享·pdf·软件工程·团队开发
hello早上好23 分钟前
Spring不同类型的ApplicationContext的创建方式
java·后端·架构
HelloWord~1 小时前
SpringSecurity+vue通用权限系统2
java·vue.js
让我上个超影吧1 小时前
黑马点评【基于redis实现共享session登录】
java·redis
BillKu2 小时前
Java + Spring Boot + Mybatis 插入数据后,获取自增 id 的方法
java·tomcat·mybatis
全栈凯哥2 小时前
Java详解LeetCode 热题 100(26):LeetCode 142. 环形链表 II(Linked List Cycle II)详解
java·算法·leetcode·链表
chxii2 小时前
12.7Swing控件6 JList
java
全栈凯哥2 小时前
Java详解LeetCode 热题 100(27):LeetCode 21. 合并两个有序链表(Merge Two Sorted Lists)详解
java·算法·leetcode·链表
YuTaoShao2 小时前
Java八股文——集合「List篇」
java·开发语言·list
PypYCCcccCc2 小时前
支付系统架构图
java·网络·金融·系统架构