Spring注解式开发之: Bean的生命周期中的初始化和销毁

Spring注解式开发之: Bean的生命周期中的初始化和销毁,第1张

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的前后能完成一系列的动作还是挺有用的。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/792141.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-05
下一篇 2022-05-05

发表评论

登录后才能评论

评论列表(0条)

保存