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()被调用
相关推荐
q***47189 分钟前
Spring中的IOC详解
java·后端·spring
vx_vxbs6622 分钟前
【SSM电影网站】(免费领源码+演示录像)|可做计算机毕设Java、Python、PHP、小程序APP、C#、爬虫大数据、单片机、文案
java·spring boot·python·mysql·小程序·php·idea
SunnyDays10111 小时前
如何使用 Java 删除 Word 文档中的水印
java·删除word文档水印
毕设源码-邱学长1 小时前
【开题答辩全过程】以 基于Java企业人事工资管理系统为例,包含答辩的问题和答案
java·开发语言
转转技术团队1 小时前
回收系统架构演进实战:与Cursor结对扫清系统混沌
java·架构·cursor
AI分享猿1 小时前
Java后端实战:SpringBoot接口遇异常请求,轻量WAF兼顾安全与性能
java·spring boot·安全
稚辉君.MCA_P8_Java2 小时前
Gemini永久会员 Java中的四边形不等式优化
java·后端·算法
DKPT2 小时前
ZGC和G1收集器相比哪个更好?
java·jvm·笔记·学习·spring
n***F8752 小时前
修改表字段属性,SQL总结
java·数据库·sql
q***69772 小时前
【Spring Boot】统一数据返回
java·spring boot·后端