Spring学习笔记之Bean生命周期
什么是Bean生命周期
在Spring容器中,当我们需要获取一个Bean实例时,会经历一系列的过程,包括BeanDefinition解析、Bean实例化、属性注入和初始化等操作,最终才能得到我们所需要的Bean实例。这整个过程就称之为Bean生命周期。
Bean生命周期可以分为以下几个阶段:
- 实例化:根据BeanDefinition创建Bean实例。
- 属性注入:对Bean实例进行属性注入。
- 初始化:执行各种初始化操作,例如Bean对象实现的
InitializingBean
接口、@PostConstruct
注解等都可以在这阶段被执行。 - 使用:Bean实例被使用。
- 销毁:当容器被关闭时,销毁Bean实例。
Bean实例化阶段
BeanDefinition解析
在Spring容器启动时,它会读取配置文件,并将配置文件中定义的BeanDefinition解析为真正的Java对象。例如,我们在配置文件中通过<bean>
标签定义了一个名为userService
的Bean:
<bean id="userService" class="com.example.UserService">
<property name="userDao" ref="userDao" />
</bean>
在解析过程中,会创建一个org.springframework.beans.factory.support.DefaultListableBeanFactory
对象,然后再通过registerBeanDefinition
方法将定义好的Bean注册到BeanFactory当中。
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
BeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(UserService.class)
.addPropertyValue("userDao", userDao())
.getBeanDefinition();
beanFactory.registerBeanDefinition("userService", beanDefinition);
Bean实例化
一旦BeanDefinition被注册成功,Spring容器就会通过反射创建出相应的Bean实例。它会调用构造函数实例化Bean对象,并在实例化时进行依赖注入。
InstantiationAwareBeanPostProcessor -> postProcessBeforeInstantiation
-> 构造函数实例化Bean对象
InstantiationAwareBeanPostProcessor -> postProcessAfterInstantiation
在无参构造函数被调用之后,会为Bean的成员变量进行依赖注入操作。例如,我们在上面的XML中定义了userService
依赖注入了userDao
,则Spring容器会在实例化userService
时自动注入相应的UserDao
对象。
Bean实例化示例
我们通过以下的示例,来看看Spring创建Bean实例的过程:
@Component
public class MyBean implements BeanNameAware, BeanFactoryAware, InitializingBean, DisposableBean {
private String name;
public void setName(String name) {
this.name = name;
}
@Override
public void setBeanName(String name) {
System.out.println("MyBean.setBeanName " + name);
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("MyBean.setBeanFactory " + beanFactory);
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("MyBean.afterPropertiesSet");
}
public String hello() {
return "Hello, " + name + "!";
}
@PreDestroy
public void preDestroy() {
System.out.println("MyBean.preDestroy");
}
@Override
public void destroy() throws Exception {
System.out.println("MyBean.destroy");
}
}
在这个示例中,我们定义了一个名为MyBean
的Bean。它实现了多个Spring生命周期接口,其中BeanNameAware
和BeanFactoryAware
用于获取Bean的名称和工厂,而InitializingBean
和DisposableBean
则用于Bean的初始化和销毁。
<bean id="myBean" class="com.example.MyBean">
<property name="name" value="world"/>
</bean>
在XML中,我们定义了一个名为myBean
的Bean,并注入了一个名为name
的属性。
我们执行以下代码,来演示Spring容器创建MyBean
实例的过程:
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
MyBean myBean = context.getBean(MyBean.class);
System.out.println(myBean.hello());
context.close();
通过运行这个程序,我们会发现控制台上依次出现了以下输出:
MyBean.setBeanName myBean
MyBean.setBeanFactory org.springframework.context.annotation.AnnotationConfigApplicationContext@5a39699c: startup date [Sun Oct 20 19:39:57 CST 2019]; root of context hierarchy
MyBean.afterPropertiesSet
Hello, world!
MyBean.preDestroy
MyBean.destroy
Bean初始化阶段
Bean初始化是指Spring容器在创建完Bean实例之后,会调用org.springframework.beans.factory.config.BeanPostProcessor
接口实现类的回调方法,来完成Bean对象的初始化工作。
BeanPostProcessor
在这个阶段中,Spring会调用BeanPostProcessor
接口实现类的两个回调方法:
BeanPostProcessor -> postProcessBeforeInitialization
-> 执行各种初始化工作
BeanPostProcessor -> postProcessAfterInitialization
其中的postProcessbeforeInitialization
和postProcessAfterInitialization
方法,分别对应Bean实例化之后的初始化操作和Bean实例化完成之后的操作。
通常我们会使用@PostConstruct
注解来标注Bean的初始化方法。这样当Spring容器进行初始化时,会自动调用这个方法。
@Component
public class MyBean {
private String name;
public void setName(String name) {
this.name = name;
}
@PostConstruct
public void init() {
System.out.println("MyBean.init");
}
public String hello() {
return "Hello, " + name + "!";
}
}
Bean初始化示例
我们通过以下的示例,来看看Spring初始化Bean的过程:
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("MyBeanPostProcessor.postProcessBeforeInitialization " + beanName);
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("MyBeanPostProcessor.postProcessAfterInitialization " + beanName);
return bean;
}
}
在这个示例中,我们定义了一个名为MyBeanPostProcessor
的BeanPostProcessor
实现类。在初始化前和初始化后分别输出Bean的名称,以便我们更好地理解阶段。
我们执行以下代码,来演示Spring容器初始化MyBean
实例的过程:
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
MyBean myBean = context.getBean(MyBean.class);
System.out.println(myBean.hello());
context.close();
通过运行这个程序,我们会发现控制台上依次出现了以下输出:
MyBeanPostProcessor.postProcessBeforeInitialization myBean
MyBean.init
MyBeanPostProcessor.postProcessAfterInitialization myBean
Hello, world!
Bean销毁阶段
DisposableBean
在Bean销毁的阶段时,Spring容器会依次调用DisposableBean
的回调方法destroy
,用于执行Bean的清理工作。
DisposableBean -> destroy
与初始化阶段类似,我们还可以使用@PreDestroy
注解来标注Bean的销毁方法。这样当Spring容器收到关闭的通知,会自动调用这个方法。
@Component
public class MyBean {
@PreDestroy
public void destroy() {
System.out.println("MyBean.destroy");
}
}
Bean销毁示例
我们通过以下的示例,来看看Spring销毁Bean的过程:
@Component
public class MyBean implements DisposableBean {
@Override
public void destroy() throws Exception {
System.out.println("MyBean.destroy");
}
}
在这个示例中,我们定义了一个名为MyBean
的Bean,实现了DisposableBean
接口。
我们执行以下代码,来演示Spring容器销毁MyBean
实例的过程:
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
MyBean myBean = context.getBean(MyBean.class);
context.close();
通过运行这个程序,我们会发现控制台上依次出现了以下输出:
MyBean.destroy
总结
Bean生命周期是Spring容器的核心部分之一,它决定了一个Bean实例的创建、初始化和销毁的过程。通过本文的介绍,我们已经了解了Spring容器在创建和销毁Bean实例时的具体过程,同时也学习了如何通过Bean生命周期接口和注解来对Bean进行定制。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Spring学习笔记之bean生命周期 - Python技术站