Bean生命周期全部完整过程不再阐述,以下主要描述四种方式完成Bean注册前后执行的初始化方法和销毁方法,Bean被注册后是怎么执行初始化和销毁方法: Bean被注册前后可以设置执行的初始化和容器关闭时执行销毁方法,这些方法是我们可以自己定义的。
方式一:
通过@Bean指定init-method和destroy-method参数的两个值
init-method = 初始化方法: 对象创建完成,并赋值好后,调用初始化方法
destroy-method = 销毁对象对方: 容器关闭时对象销毁 (如果是多实例容器不会去调用销毁方法)
配置类代码:
@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调用初始化方法...
容器中有: life
life调用销毁方法...
分析说明: life这个bean确实执行了初始化和销毁方法,spring容器启动会注册很多有关的bean,但我只截取了实体类bean以及演示的信息(之后以下的控制台输出都会只截取有用的输出)
方式二:
通过Bean实现InitializingBean和DisposableBean接口
初始化: 对象创建完成,并赋值好后,调用初始化方法
销毁对象: 容器关闭时对象销毁 (如果是多实例容器不会去调用销毁方法)
配置类代码 :
@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();
控制台输出:
life2调用初始化方法...(实现接口方式)
容器中有: life2
life2调用销毁方法...(实现接口方式)
分析说明: 和方式一基本差不多只不过一个是用注解实现一个是用接口来实现
方式三:
可以使用JSR250,直接在实体类上加注解,比起方式二实现接口方式更加方便
@PostConstruct注解: 在Bean创建完成并且属性赋值完成,来执行初始化方法
@PreDestroy注解: 在容器销毁Bean之前进行清理工作
配置类代码:
@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();
控制台输出:
dog调用初始化方法...(使用@PostConstruct注解方式)
容器中有: dog
dog调用销毁方法...(使用@PreDestroy注解方式)
分析说明: 比起方式一和方式二,用注解更加简单
方式四:
使用后置处理器方式,该处理器实现BeanPostProcessor接口(自己也是个Bean同样会被加载到容器中)
该接口中的postProcessBeforeInitialization方法: 在舒初始化之前工作
该接口中的postProcessAfterInitialization方法: 在初始化之后工作
配置类代码:
/**
* 采用后置处理器方式
*/
@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);
}
控制台输出:
cat被创建...
后置处理器bean初始化前:cat com.entity.Cat@2cbb3d47
后置处理器bean初始化后:cat com.entity.Cat@2cbb3d47
分析说明: 用实现BeanPostProcessor接口的后置处理器类可以在每个bean注册前后执行方法,可以完成一些准备工作以及初始化后的其他工作,可见用后置处理器类注册Bean的前后能完成一系列的动作还是挺有用的。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)