1. Bean的生命周期完整图示
Bean的生命周期包括 4 个阶段:实例化Instantiation 、属性赋值Populate 、初始化Initalization 、销毁Destruction。其中这 4 个阶段又进一步细分,下图列举了完整的Bean创建至销毁的流程:
2. 编码验证
2.1 Bean的实例化与属性赋值
(1)定义Person类,类中包含有参构造方法和name属性的setter方法,用于验证Bean的实例化与属性赋值。
/**
* @author name: silk
* @version 1.0
* @description: Bean
* @date 2024/3/29 20:30
*/
public class Person {
private String name;
public Person() {
System.err.println("Person's constructor is called...");
}
/***
* @description: 在Bean的生命周期中,首先进行实例化,再属性赋值
* @author name silk
* @date: 2024/3/29 20:47
*/
public void setName(String name) {
System.err.println("setName method is called...");
this.name = name;
}
}
(2)XML配置Bean的定义
<?xml version="1.0" encoding="UTF-8"?>
<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.wyw.learn.beanlife.Person">
<property name="name" value="xiaoWang"/>
</bean>
</beans>
(3)DemoApplication启动类
package com.wyw.learn.beanlife;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @author name: silk
* @version 1.0
* @description: 主程序
* @date 2024/3/29 20:34
*/
@ComponentScan("com.wyw.learn")
public class DemoApplication {
public static void main(String[] args) {
System.err.println("======Spring容器初始化开始======");
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beanLifeApplicationContext.xml");
System.err.println("======Spring容器初始化完成======");
System.err.println("--------------------------------------");
System.err.println("=======Spring容器准备关闭=======");
context.close();
System.err.println("========Spring容器已关闭========");
}
}
(4)测试结果
2.2 Bean的初始化
Bean的初始化一般通过以下 4 种方式:
- 实现BeanPostProcessor接口,重写postProcessBeforeInitialization()方法;
- 使用@PostConstruct注解标识某初始化方法;
- 实现InitializingBean接口,重写afterPropertiesSet()方法;
- 在XML中配置了init-method属性,则会自动调用其配置的初始化方法;
接下来,我们探索一下这几种初始化方式的执行顺序:
(1)Person类
/**
* @author name: silk
* @version 1.0
* @description: Bean
* @date 2024/3/29 20:30
*/
@Component
public class Person implements InitializingBean, DisposableBean {
private String name;
public Person() {
System.err.println("Person's constructor is called...");
}
/***
* @description: 在Bean的生命周期中,首先进行实例化,再属性赋值,然后执行init-method标记的方法
* @author name silk
* @date: 2024/3/29 20:47
*/
public void setName(String name) {
System.err.println("setName method is called...");
this.name = name;
}
@PostConstruct
public void postConstruct() {
System.err.println("@PostConstruct...");
}
@Override
public void afterPropertiesSet() throws Exception {
System.err.println("InitializingBean#afterPropertiesSet...");
}
/***
* @description: init-method
* @author name silk
* @date: 2024/3/29 20:33
*/
public void initMethod() {
System.err.println("init-method...");
}
@Override
public String toString() {
return "Person{" + "name=" + name + '}';
}
}
(2)PersonBeanPostProcessor类,实现BeanPostProcessor接口
package com.wyw.learn.beanlife;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;
/**
* @author name: silk
* @version 1.0
* @description: TODO
* @date 2024/3/29 21:08
*/
@Component
public class PersonBeanPostProcessor implements BeanPostProcessor {
// 常规情况这个构造器不写,这里主要为了证明前面的几条打印信息属于该PersonBeanPostProcessor
public PersonBeanPostProcessor() {
System.err.println("PersonBeanPostProcessor's constructor is called...");
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.err.println("postProcessBeforeInitialization");
return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.err.println("postProcessAfterInitialization");
return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
}
}
(3)PersonConfig类,代替XML文件创建Person对应的Bean对象
package com.wyw.learn.beanlife;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author name: silk
* @version 1.0
* @description: Person配置类
* @date 2024/3/29 20:59
*/
@Configuration
public class PersonConfig {
/***
* @description: @Bean注解中有属性:initMethod和destroyMethod,这两个属性的作用与XML配置中的init-method和destroy-method相同
* @author name silk
* @date: 2024/3/29 21:01
*/
@Bean(initMethod = "initMethod")
public Person person() {
return new Person();
}
}
(4)DemoApplication启动类
package com.wyw.learn.beanlife;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @author name: silk
* @version 1.0
* @description: 主程序
* @date 2024/3/29 20:34
*/
@ComponentScan("com.wyw.learn")
public class DemoApplication {
public static void main(String[] args) {
System.err.println("======Spring容器初始化开始======");
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("com.wyw.learn.beanlife");
System.err.println("======Spring容器初始化完成======");
System.err.println("--------------------------------------");
System.err.println("=======Spring容器准备关闭=======");
context.close();
System.err.println("========Spring容器已关闭========");
}
}
(5)测试结果
2.3 Bean的销毁
(1)Person类,新增与Bean销毁相关的方法
package com.wyw.learn.beanlife;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
/**
* @author name: silk
* @version 1.0
* @description: Bean
* @date 2024/3/29 20:30
*/
@Component
public class Person implements InitializingBean, DisposableBean {
private String name;
public Person() {
System.err.println("Person's constructor is called...");
}
/***
* @description: 在Bean的生命周期中,首先进行实例化,再属性赋值,然后执行init-method标记的方法
* @author name silk
* @date: 2024/3/29 20:47
*/
public void setName(String name) {
System.err.println("setName method is called...");
this.name = name;
}
@PostConstruct
public void postConstruct() {
System.err.println("@PostConstruct...");
}
@Override
public void afterPropertiesSet() throws Exception {
System.err.println("InitializingBean#afterPropertiesSet...");
}
/***
* @description: init-method
* @author name silk
* @date: 2024/3/29 20:33
*/
public void initMethod() {
System.err.println("init-method...");
}
@PreDestroy
public void preDestroy() {
System.err.println("@PreDestroy...");
}
@Override
public void destroy() throws Exception {
System.err.println("DisposableBean#destroy...");
}
/***
* @description: destroy-method
* @author name silk
* @date: 2024/3/29 20:33
*/
public void destroyMethod() {
System.err.println("destroy-method...");
}
@Override
public String toString() {
return "Person{" + "name=" + name + '}';
}
}
(2)PersonConfig类,@Bean注解中配置destory-method属性
package com.wyw.learn.beanlife;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author name: silk
* @version 1.0
* @description: Person配置类
* @date 2024/3/29 20:59
*/
@Configuration
public class PersonConfig {
/***
* @description: @Bean注解中也有属性:initMethod和destroyMethod,这两个属性的作用与XML配置中的init-method和destroy-method相同
* @author name silk
* @date: 2024/3/29 21:01
*/
@Bean(initMethod = "initMethod", destroyMethod = "destroyMethod")
public Person person() {
return new Person();
}
}
(3)PersonBeanPostProcessor类和主启动类DemoApplication类不变
(4)测试结果(展示了完整的从Bean的创建至销毁全过程信息)
最后,得出结论,Bean的初始化顺序为:BeanPostProcessor → @PostConstruct → InitializingBean → init-method;销毁顺序为:@PreDestroy → DisposableBean → destroy-method。