Bean的生命周期,尤其是Bean从实例化到可以使用,过程较为复杂,所以建议自己coding一遍来加深理解。
该周期中涵盖了Spring Aware接口,Spring PostProcessor后置处理器等等,首次接触时可能会觉得晦涩难懂,结合应用场景更有助于理解。
生命周期
Spring Aware接口
org.springframework.beans.factory.Aware
使得自定义Bean可以识别利用Spring容器的资源,比如,
- BeanNameAware.setBeanName(String)
,可以在Bean中得到它在IOC容器中的Bean的实例的名字。
- BeanFactoryAware.setBeanFactory(BeanFactory)
,可以在Bean中得到Bean所在的IOC容器,从而直接在Bean中使用IOC容器的服务。
- ApplicationContextAware.setApplicationContext(ApplicationContext)
,可以在Bean中得到Bean所在的应用上下文,从而直接在Bean中使用上下文的服务。
- MessageSourceAware,在Bean中可以得到消息源。
- ApplicationEventPublisherAware,在bean中可以得到应用上下文的事件发布器,从而可以在Bean中发布应用上下文的事件。
- ResourceLoaderAware,在Bean中可以得到ResourceLoader,从而在bean中使用ResourceLoader加载外部对应的Resource资源。
如非必要,Spring官方不推荐自定义Bean实现Aware接口,这会增加代码与Spring 框架的耦合性。
Spring PostProcessor
BeanFactoryPostProcessor可以对bean的配置信息进行操作。结合Bean的生命周期,Spring IOC容器允许BeanFactoryPostProcessor读取配置信息并且能够在容器实例化任何其他bean之前改变配置信息。
BeanPostProcessor可以在Spring完成Bean实例化,配置,初始化之后实现自己的业务逻辑。
Spring Aware和PostProcessor都是提供了用户利用Spring IoC添加业务逻辑进一步定制Bean。
实例
public class MyBean implements BeanNameAware, BeanFactoryAware, ApplicationContextAware, BeanClassLoaderAware,
InitializingBean, DisposableBean {
private String name;
private String description;
public MyBean() {
System.out.println("**MyBean** construct.");
}
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
System.out.println("**MyBean** BeanClassLoaderAware.setBeanClassLoader: " + classLoader.getClass());
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("**MyBean** BeanFactoryAware.setBeanFactory: " + beanFactory.getClass());
}
@Override
public void setBeanName(String s) {
System.out.println("**MyBean** BeanNameAware.getBeanName: " + s);
}
@Override
public void destroy() throws Exception {
System.out.println("**MyBean** DisposableBean.destroy");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("**MyBean** InitializingBean.afterPropertiesSet");
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("**MyBean** ApplicationContextAware.setApplicationContext");
}
@Override
protected void finalize() throws Throwable {
System.out.println("**MyBean** MyBean finalized.");
}
@PostConstruct
public void springPostConstruct() {
System.out.println("**MyBean** @PostConstruct");
}
// xml文件中的init-method
public void myInitMethod() {
System.out.println("**MyBean** init-method");
}
@PreDestroy
public void springPreDestroy() {
System.out.println("**MyBean** @PreDestroy");
}
// xml文件中的destroy-method
public void mydestroyMethod() {
System.out.println("**MyBean** destory-method");
}
@Autowired
public void setName(String name) {
this.name = name;
System.out.println("**MyBean** setName");
}
@Autowired
public void setDescription(String description) {
this.description = description;
System.out.println("**MyBean** setDescription");
}
@Override
public String toString() {
return "MyBean{" +
"name='" + name + '\'' +
", description='" + description + '\'' +
'}';
}
}
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
public MyBeanFactoryPostProcessor() {
super();
System.out.println("[MyBeanFactoryPostProcessor] constructor");
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
System.out.println("[MyBeanFactoryPostProcessor] postProcessBeanFactory");
}
}
public class MyBeanPostProcessor implements BeanPostProcessor {
public MyBeanPostProcessor() {
super();
System.out.println("[MyBeanPostProcessor] constructor.");
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("[MyBeanPostProcessor] postProcessBeforeInitialization: " + bean.getClass() + ": " + beanName);
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("[MyBeanPostProcessor] postProcessAfterInitialization: " + bean.getClass() + ": " + beanName);
return bean;
}
}
public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
public MyInstantiationAwareBeanPostProcessor() {
super();
System.out.println("[MyInstantiationAwareBeanPostProcessor] constructor.");
}
// 接口方法、实例化Bean之前调用
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
System.out.println("[MyInstantiationAwareBeanPostProcessor] postProcessBeforeInstantiation");
return null;
}
// 接口方法、实例化Bean之前调用
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
System.out.println("[MyInstantiationAwareBeanPostProcessor] postProcessAfterInstantiation");
return true;
}
// 接口方法、设置某个属性时调用
@Override
public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
System.out.println("[MyInstantiationAwareBeanPostProcessor] postProcessPropertyValues");
// 注意返回结果,否则会无法正确Bean的属性
return pvs;
}
}
public class LifeCycleApplication {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("lifecycle.xml");
System.out.println("[Application] before get bean");
MyBean bean = (MyBean) context.getBean("myBean");
System.out.println("[Application] after get bean");
System.out.println(bean);
((ClassPathXmlApplicationContext) context).registerShutdownHook();
}
}
lifecycle.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
http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.example.LifeCycle"/>
<bean id="myBean" class="com.example.LifeCycle.MyBean" init-method="myInitMethod"
destroy-method="mydestroyMethod">
</bean>
<bean class="com.example.LifeCycle.MyBeanPostProcessor"/>
<bean class="com.example.LifeCycle.MyBeanFactoryPostProcessor"/>
<bean class="com.example.LifeCycle.MyInstantiationAwareBeanPostProcessor"/>
</beans>
运行结果:
...
[MyBeanFactoryPostProcessor] constructor
...
MyBeanFactoryPostProcessor] postProcessBeanFactory
...
[MyBeanPostProcessor] constructor
...
[MyInstantiationAwareBeanPostProcessor] constructor
[MyInstantiationAwareBeanPostProcessor] constructor
**MyBean** construct.
...
[MyInstantiationAwareBeanPostProcessor] postProcessAfterInstantiation
[MyInstantiationAwareBeanPostProcessor] postProcessPropertyValues
...
*MyBean** setName
**MyBean** setDescription
**MyBean** BeanNameAware.getBeanName: myBean
**MyBean** BeanClassLoaderAware.setBeanClassLoader: class sun.misc.Launcher$AppClassLoader
**MyBean** BeanFactoryAware.setBeanFactory: class org.springframework.beans.factory.support.DefaultListableBeanFactory
**MyBean** ApplicationContextAware.setApplicationContext
[MyBeanPostProcessor] postProcessBeforeInitialization: class com.example.LifeCycle.MyBean: myBean
...
**MyBean** init-method
...
MyBean{name='Gigi', description='description'}
...
**MyBean** @PreDestroy
**MyBean** DisposableBean.destroy
**MyBean** destory-method
一些建议
不建议使用InitializingBean, DisposableBean,因为这个会增加代码与Spring框架的耦合性。
@PostConstruct,@PreDestroy是JavaX的标准,而非Java,Spring定义的注解,使用时应该注意。
将Bean从Spring IoC中移除之前需要释放持有的资源,建议在destroy-method中写释放资源的代码。
Ref:
1. https://www.concretepage.com/spring/spring-bean-life-cycle-tutorial
2. XXXAware讲解:https://www.baeldung.com/spring-bean-name-factory-aware
3. 后置处理器XXXPostProcessor讲解:
http://wiki.jikexueyuan.com/project/spring/bean-post-processors.html
https://www.jianshu.com/p/fb39f568cd5e