最新下载
热门教程
- 1
 - 2
 - 3
 - 4
 - 5
 - 6
 - 7
 - 8
 - 9
 - 10
 
Bean的三种自定义初始化和销毁代码方法
时间:2022-06-29 01:56:13 编辑:袖梨 来源:一聚教程网
本篇文章小编给大家分享一下Bean的三种自定义初始化和销毁代码方法,文章代码介绍的很详细,小编觉得挺不错的,现在分享给大家供大家参考,有需要的小伙伴们可以来看看。
一. 三种方法概述
在配置类中指定 @Bean(initMethod = “init”,destroyMethod = “destory”)注解
实现InitializingBean接口并重写其afterPropertiesSet方法,实现DisposableBean接口并重写destroy方法
利用java的JSR250规范中的@PostConstruct标注在init方法上,@PreDestroy标注在destroy方法上
二. 方法详述
1. 方法1:配置类中指定
示例代码
public class CarA {
    public CarA() {
        System.out.println("CarA。。。构造函数");
    }
    public void initCarA(){
        System.out.println("CarA的init()方法");
    }
    public void destroyCarA(){
        System.out.println("CarA的destroy()方法");
    }
}
@Configuration
public class ConfigTest {
    @Bean(initMethod = "initCarA",destroyMethod = "destroyCarA")
    public CarA carA(){
        return new CarA();
    }
}
执行结果
CarA。。。构造函数
CarA的init()方法
服务启动
CarA的destroy()方法
2. 方法2:实现接口并重写方法
2.1 示例代码
public class CarB implements InitializingBean, DisposableBean {
    public CarB() {
        System.out.println("CarB。。。构造函数");
    }
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("CarB。。。afterPropertiesSet()方法执行");
    }
    @Override
    public void destroy() throws Exception {
        System.out.println("CarB。。。destroy()方法执行");
    }
}
@Configuration
public class ConfigTest {
    @Bean
    public CarB carB(){
        return new CarB();
    }
}
执行结果
CarB。。。构造函数
CarB。。。afterPropertiesSet()方法执行
服务启动
CarB。。。destroy()方法执行
2.2 概述
Spring 开放了扩展接口,允许我们自定义 bean 的初始化和销毁方法。即当 Spring 容器在 bean 进行到相应的生命周期阶段时,会自动调用我们自定义的初始化和销毁方法。这两个扩展接口是 InitializingBean 和 DisposableBean 。
InitializingBean 接口说明:该接口为 bean 提供了 bean 属性初始化后的处理方法,它只有 afterPropertiesSet 一个方法,凡是实现此接口的类,在 bean 的属性初始化后都会执行该方法。
package org.springframework.beans.factory;
public interface InitializingBean {
    void afterPropertiesSet() throws Exception;
}
DisposableBean 接口说明:该接口为单例 bean 提供了在容器销毁 bean 时的处理方法,它只有 destroy 一个方法,凡是实现此接口的类,在 bean 被销毁时都会执行该方法。
package org.springframework.beans.factory;
public interface DisposableBean {
    void destroy() throws Exception;
}
2.3 方法1 && 方法2
相同点:都是在 bean 属性初始化之后需要执行的初始化方法。
不同点
方法1:代码不与Spring耦合;执行效率较低(通过反射来执行initMethod 方法)
方法2:代码与Spring紧耦合;速度更快(将 bean 强制转换成 InitializingBean 接口类型,然后直接调用 afterPropertiesSet 方法)
说明:afterPropertiesSet 和 initMethod 可以同时存在,但是 afterPropertiesSet 方法是在 initMethod 方法之前执行的。
一个 bean 从创建到初始化的过程总结
通过构造器创建 bean
属性注入
执行 afterPropertiesSet 方法
执行 initMethod 方法
3. 方法3:利用java的JSR250规范
代码示例
public class CarC {
    public CarC() {
        System.out.println("CarC。。。构造函数");
    }
    @PostConstruct
    public void initCarC(){
        System.out.println("CarC。。。初始化方法initCarC()");
    }
    @PreDestroy
    public void destroyCarC(){
        System.out.println("CarC。。。销毁方法destroyCarC");
    }
}
@Configuration
public class ConfigTest {
    @Bean
    public CarC carC(){
        return new CarC();
    }
}
执行结果
CarC。。。构造函数
CarC。。。初始化方法initCarC()
服务启动
CarC。。。销毁方法destroyCarC
spring初始化后获取自定义注解Bean
目的是通过注解将特定类的信息(如接口编号)与类关联,之后可通过接口编号获取对应bean来执行对应逻辑。
一.新建注解类
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Service
public @interface ServiceCode {
    String code() default ""; 
    String className() default "";
}
包含接口编号和beanName信息。
二.新建接口类
@ServiceCode(code = "100010", className = "echoService")
@Service("echoService")
public class EchoService { 
}
三.实现接口ApplicationListener
来监听spring容器初始化完成后执行:
@Component @Order(1) public class ServiceInitListener implements ApplicationListener{ private static final Logger LOGGER = LoggerFactory.getLogger(ServiceInitListener.class); @Override public void onApplicationEvent(ContextRefreshedEvent event) { ApplicationContext applicationContext = event.getApplicationContext(); //注意 需要时根容器才能通过注解获取到bean,比如event直接获取的容器中只有一些公共注册bean if (applicationContext.getParent() != null) { applicationContext = applicationContext.getParent(); } Map beansWithAnnotation = applicationContext.getBeansWithAnnotation(ServiceCode.class); for (Object bean : beansWithAnnotation.values()) { ServiceCode annotation = bean.getClass().getAnnotation(ServiceCode.class); String code = annotation.code(); String className = annotation.className(); //注册接口编号和beanName //在统一入口可通过code获取beanName,然后通过springContext获取对应bean执行自定义逻辑 //或者完成其他逻辑 } } } 
注意:
ContextRefreshedEvent获取到的上下文环境不是根spring容器,其中只有部分spring内置bean,无法通过注解获取到自定义bean,需要获取其父容器来完成操作。我第一次获取是beanList总为空,后来发现其容器内部bean没有自定义的service bean,获取父容器后操作一切正常。
通过@Order注解来定制执行顺序,越小越优先执行。
相关文章
- 二重螺旋炼火的典狱长通关攻略 11-04
 - 二重螺旋千面歌者的忧郁任务流程攻略 11-04
 - 二重螺旋金色魔灵获取途径 11-04
 - 明日方舟协律有什么技能及天赋 11-04
 - 三国望神州臧霸角色如何 11-04
 - 漫威秘法狂潮神奇先生怎么玩 11-04