Bean生命周期全部完整过程不再阐述,以下主要描述四种方式完成Bean注册前后执行的初始化方法和销毁方法,Bean被注册后是怎么执行初始化和销毁方法: Bean被注册前后可以设置执行的初始化和容器关闭时执行销毁方法,这些方法是我们可以自己定义的。
方式一:
配置类代码:
@Configuration
public class Config1 {
/**
* initMethod: 该bean被创建并赋值完调用的初始化方法
* destroy: 容器关闭时调用该bean的销毁方法
* @return
*/
@Bean(initMethod = "init", destroyMethod = "destroy")
public Life life(){
return new Life();
}
}
实体类代码: 因为只声明注册一个Life类的Bean
public class Life {
public void init(){
System.out.println("life调用初始化方法...");
}
public void destroy(){
System.out.println("life调用销毁方法...");
}
}
测试代码:
//根据配置类启动容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Config1.class);
//获取所有已被注册的bean的id
String[] ids = applicationContext.getBeanDefinitionNames();
for(String s : ids){
System.out.println("容器中有: " + s);
}
//关闭容器
applicationContext.close();
控制台输出:
分析说明: life这个bean确实执行了初始化和销毁方法,spring容器启动会注册很多有关的bean,但我只截取了实体类bean以及演示的信息(之后以下的控制台输出都会只截取有用的输出)
方式二:
配置类代码 :
@Configuration
public class Config2 {
@Bean
public Life2 life2(){ //注册life2这个bean
return new Life2();
}
}
实体类代码:
//和Life类区别是本类以实现接口方式完成初始化和销毁方法的调用
public class Life2 implements InitializingBean, DisposableBean {
//此Bean被创建并且属性被赋值后调用的初始化方法
@Override
public void destroy() throws Exception {
System.out.println("life2调用销毁方法...(实现接口方式)");
}
//容器关闭调用的销毁方法
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("life2调用初始化方法...(实现接口方式)");
}
}
测试代码:
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Config2.class);
//获取所有已被注册的Bean的id
String[] ids = applicationContext.getBeanDefinitionNames();
for(String s : ids){
System.out.println("容器中有: " + s);
}
//关闭容器
applicationContext.close();
控制台输出:
分析说明: 和方式一基本差不多只不过一个是用注解实现一个是用接口来实现
方式三:
配置类代码:
@Configuration
public class Config3 {
@Bean
public Dog dog(){
return new Dog();
}
}
实体类代码:
//采用注解方法完成Bean注册前后的初始化方法和容器关闭时的销毁方法
public class Dog {
//对象创建并赋值后调用的初始化方法
@PostConstruct
public void init(){
System.out.println("dog调用初始化方法...(使用@PostConstruct注解方式)");
}
//容器关闭调用的销毁方法
@PreDestroy
public void destroy(){
System.out.println("dog调用销毁方法...(使用@PreDestroy注解方式)");
}
}
测试代码:
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Config3.class);
//获取所有已被注册的Bean的id
String[] ids = applicationContext.getBeanDefinitionNames();
for(String s : ids){
System.out.println("容器中有: " + s);
}
applicationContext.close();
控制台输出:
分析说明: 比起方式一和方式二,用注解更加简单
方式四:
配置类代码:
/**
* 采用后置处理器方式
*/
@Configuration
@ComponentScan(value = "com.entity") //扫描com.entity包下的所有类
public class Config4 {
}
实体类代码: 我com.entity包下有Cat类和MyBeanPostProcessor后置处理器类
@Component
public class Cat {
public Cat(){
System.out.println("cat被创建...");
}
}
后置处理器代码:
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
/**
* 每个bean实例初始化之前调用的方法
* @param bean 容器刚创建的实例
* @param beanName 实例的名字
* @return //返回bean(原来的bean不用动)
* @throws BeansException
*/
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("后置处理器bean初始化前:" + beanName +" " + bean);
return bean;
}
/**、
* 每个bean实例初始化后调用的方法
* @param bean 容器刚创建的实例
* @param beanName 实例的名字
* @return //返回bean(原来的bean不用动)
* @throws BeansException
*/
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("后置处理器bean初始化后:" + beanName +" " + bean);
return bean;
}
}
测试代码:
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Config4.class);
//获取所有已被注册的Bean的id
String[] ids = applicationContext.getBeanDefinitionNames();
for(String s : ids){
System.out.println("容器中有: " + s);
}
控制台输出:
分析说明: 用实现BeanPostProcessor接口的后置处理器类可以在每个bean注册前后执行方法,可以完成一些准备工作以及初始化后的其他工作,可见用后置处理器类注册Bean的前后能完成一系列的动作还是挺有用的。