持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第3天,点击查看活动详情
Spring bean生命周期流程图
- 首先容器启动后,会对scope为singleton且非懒加载的bean进行实例化
- 按照Bean定义配置信息,注入所有的属性
- 如果Bean实现了BeanNameAware接口,会回调该接口的setBeanName()方法,传入该Bean的id,此时该Bean就获得了自己在配置文件中的id
- 如果Bean实现了BeanFactoryAware接口,会回调该接口的setBeanFactory()方法,传入该Bean的BeanFactory,这样该Bean就获得了自己所在的BeanFactory
- 如果Bean实现了ApplicationContextAware接口,会回调该接口的setApplicationContext()方法,传入改Bean的ApplicationContext,这样该Bean就获得了自己所在的ApplicationContext
- 如果该Bean实现了BeanPostProcessor接口,则会回调该接口的postProcessBeforeInitialzation()方法
- 如果Bean实现了InitializingBean接口,则会回调该接口的afterPropertiesSet()方法
- 如果Bean配置了init-method方法,则会执行init-method配置的方法
- 如果有Bean实现了BeanPostProcessor接口,则会回调该接口的postProcessAfterInitialization()方法
- 经过流程9之后,就可以正式使用该Bean了,对于scope为singleton的Bean,Spring的ioc容器中会缓存一份该bean的实例,而对于scope为prototype的Bean,每次被调用都会new一个新的对象,生命周期就交给调用方管理了,不再是Spring容器进行管理了
- 容器关闭后,如果Bean实现了DisposableBean接口,则会回调该接口的destroy()方法
- 如果Bean配置了destroy-method方法,则会执行destroy-method配置的方法,至此整个Bean的生命周期结束
代码演示
- 创建一个Person类,该类实现了BeanNameAware, BeanFactoryAware, ApplicationContextAware, InitializingBean, DisposableBean五个接口
public class Person implements BeanNameAware, BeanFactoryAware, ApplicationContextAware, InitializingBean, DisposableBean {
private String name;
public Person() {
System.out.println("Person类构造方法");
}
public void setName(String name) {
this.name = name;
System.out.println("set方法被调用");
}
// 自定义的初始化函数
public void myInit() {
System.out.println("myInit被调用");
}
// 自定义的销毁方法
public void myDestroy() {
System.out.println("myDestroy被调用");
}
@Override
public void setBeanName(String s) {
System.out.println("setBeanName被调用,beanName:" + s);
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("setBeanFactory被调用,beanFactory");
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("setApplicationContext被调用");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("afterPropertiesSet被调用");
}
@Override
public void destroy() throws Exception {
System.out.println("destroy被调用");
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '' +
'}';
}
}
- 创建一个MyBeanPostProcessor类,该类实现了BeanPostProcessor接口
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("postProcessBeforeInitialization被调用");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("postProcessAfterInitialization被调用");
return bean;
}
}
- applicationContext.xml文件中配置
- 配置bean的id为person,并且配置了init-method和destroy-method,为该Bean配置了属性name为RG的值
- 配置bean的id为postProcessor
<?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 id="person" class="com.rg.domain.Person" init-method="myInit" destroy-method="myDestroy">
<property name="name" value="RG"/>
</bean>
<!-- 配置自定义的后置处理器 -->
<bean id="postProcessor" class="com.rg.processor.MyBeanPostProcessor"/>
</beans>
- 测试类
@Test
public void personTest() {
System.out.println("开始初始化容器");
// 获取到了spring上下文对象,借助上下文对象可以获取到IOC容器中bean对象
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
System.out.println("xml加载完毕");
// 使用上下文对象从IOC容器中获取到了bean对象
Person person = (Person) applicationContext.getBean("person");
System.out.println(person);
System.out.println("关闭容器");
applicationContext.close();
}
- 打印结果