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()被调用
相关推荐
鹿屿二向箔23 分钟前
基于SSM(Spring + Spring MVC + MyBatis)框架搭建一个病人跟踪信息管理系统
spring·mvc·mybatis
呜呼~2251428 分钟前
前后端数据交互
java·vue.js·spring boot·前端框架·intellij-idea·交互·css3
飞的肖36 分钟前
从测试服务器手动热部署到生产环境的实现
java·服务器·系统架构
周伯通*41 分钟前
策略模式以及优化
java·前端·策略模式
两点王爷1 小时前
Java读取csv文件内容,保存到sqlite数据库中
java·数据库·sqlite·csv
问道飞鱼1 小时前
【Springboot知识】Springboot进阶-实现CAS完整流程
java·spring boot·后端·cas
抓哇小菜鸡1 小时前
WebSocket
java·websocket
single5941 小时前
【c++笔试强训】(第四十五篇)
java·开发语言·数据结构·c++·算法
Q_19284999061 小时前
基于Spring Boot的电影网站系统
java·spring boot·后端
老鑫安全培训2 小时前
从安全角度看 SEH 和 VEH
java·网络·安全·网络安全·系统安全·安全威胁分析