bean的生命周期
bean的生命周期指bean从创建到最终销毁要经历的阶段,简单来看,spring中bean的生命周期分为下面几个步骤。
青铜版
通过代码演示spring bean的生命周期:
public class Monkey {
private String nickname;
public Monkey() {
System.out.println("1.创建对象");
}
@Value("wukong")
public void setNickname(String nickname) {
System.out.println("2.设置属性");
this.nickname = nickname;
}
public void init() {
System.out.println("3.初始化方法");
}
public void myDestroy() {
System.out.println("5.销毁方法");
}
}
创建Monkey配置类将对象放入容器
@Configuration
@ComponentScan(basePackages = "com.monkey1024")
public class MonkeyConfiguration {
//将对象放入容器并指定init和destroy方法
@Bean(name = "monkey",initMethod = "init",destroyMethod = "myDestroy")
public Monkey monkeyInstance() {
return new Monkey();
}
}
创建测试代码,执行后可以看到对应的打印结果
//通过注解创建容器对象
ApplicationContext context = new AnnotationConfigApplicationContext(MonkeyConfiguration.class);
Monkey monkey = context.getBean("monkey", Monkey.class);
System.out.println("4.使用:" + monkey);
((AnnotationConfigApplicationContext) context).close();
bean的生命周期之BeanPostProcessor接口
在青铜版的生命周期之间,spring提供了一些钩子(hook),我们可以利用钩子在bean生命周期的某个阶段实现特定的需求。例如可以利用BeanPostProcessor接口在bean初始化前后做一些操作,该接口的实现类被称为bean后处理器。
spring bean生命周期的白银版本:
创建一个类实现BeanPostProcessor接口,并重写2个方法:
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("执行before:" + bean + "===" + beanName);
//这里要将bean返回
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("执行after:" + bean + "===" + beanName);
return bean;
}
}
测试代码同上,运行之后观察打印结果
bean的生命周期之InstantiationAwareBeanPostProcessor接口
spring在该接口中提供了钩子,我们可以利用这些钩子在bean对象创建之前和之后做一些事情。
spring bean生命周期的黄金版
创建实现类
@Component
public class MyInstantiationProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
System.out.println("执行InstantiationAwareBeanPostProcessor的before方法");
//若返回非null,则不会执行初始化和BeanPostProcessor中的方法
return InstantiationAwareBeanPostProcessor.super.postProcessBeforeInstantiation(beanClass, beanName);
}
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
System.out.println("执行InstantiationAwareBeanPostProcessor的after方法");
//若返回false,则不会注入bean中的属性
return InstantiationAwareBeanPostProcessor.super.postProcessAfterInstantiation(bean, beanName);
}
}
测试代码同上,运行观察结果。
bean的生命周期之其他接口
Aware相关接口
从使用上来看,spring中的对象分为自定义对象和容器对象。若在自定义对象中获取容器对象时就会用到aware相关接口,spring会调用对应的set方法传入容器对象。比如自己定义了一个Monkey类,可以利用aware的子类来获取ApplicationContext对象。
//实现ApplicationContextAware
public class Monkey implements ApplicationContextAware {
private String nickname;
private ApplicationContext applicationContext;
//spring会调用该方法将applicationContext对象传入
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
InitializingBean接口
该接口中只有1个方法,会在BeanPostProcessor中的before之后,初始化方法之前执行。
DisposableBean接口
该接口只有1个方法,会在使用之后,销毁方法之前执行。
bean生命周期之铂金版
修改Monkey类如下:
public class Monkey implements ApplicationContextAware, InitializingBean, DisposableBean {
private String nickname;
public Monkey() {
System.out.println("1.创建对象");
}
@Value("wukong")
public void setNickname(String nickname) {
System.out.println("2.设置属性");
this.nickname = nickname;
}
public void init() {
System.out.println("3.初始化方法");
}
public void myDestroy() {
System.out.println("5.销毁方法");
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("ApplicationContextAware");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("InitializingBean");
}
@Override
public void destroy() throws Exception {
System.out.println("DisposableBean");
}
}
运行之前的测试代码观察结果。