总结Bean的三种自定义初始化和销毁方法
作者:zijikanwa 发布时间:2023-01-05 13:38:09
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<ContextRefreshedEvent> {
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<String, Object> 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注解来定制执行顺序,越小越优先执行。
来源:https://blog.csdn.net/zijikanwa/article/details/120768948


猜你喜欢
- 基本思想归并排序采取分治的思想进行排序,借用一张图片说明一下将n个元素从中间切开,分成两部分。(左边可能比右边多1个数) 将步骤1分成的两部
- gcc 命令使用 gcc 编译 c语言-c 编译、汇编到目标代码,不进行链接,也就是直接生成目标文件-o 将输出的文件以指定文件名来储存,有
- 一、通过html页面打开Android本地的app1、首先在编写一个简单的html页面<html> &nb
- 目录一、什么是vector数组二、vector的基本操作vector数组的初始化向vector中插入元素删除元素遍历数组利用vector创建
- 本文实例为大家分享了Android实现图片点击放大的具体代码,供大家参考,具体内容如下在我的项目中,有点击图片banner后放大浏览的功能。
- 本文实例讲述了Java比较两个List的值是否相等的方法。分享给大家供大家参考。具体如下:假设两个队列 {1,2,3,4} 和 {4,3,2
- 在源代码中设置断点,然后进行点击调试若要启用反汇编窗口,请在工具>选项(或工具> 选项>调试下,选择启用地址级调试。若要在
- 本文实例为大家分享了Java实现五子棋游戏的具体代码,供大家参考,具体内容如下学习目的:熟悉java中swing类与java基础知识的巩固.
- package com;import java.util.Arrays; public class sjf { &nbs
- 本文实例讲述了Android编程实现下载时主界面与详细界面一致更新的方法。分享给大家供大家参考,具体如下:1、创建监听管理类public c
- 实现“摇一摇”功能,其实很简单,就是检测手机的重力感应,具体实现代码如下:1、在 AndroidManifest.xml 中添加操作权限2、
- 本文实例讲述了WCF实现的计算器功能。分享给大家供大家参考,具体如下:对于WCF,我们有了前面的理论基础,今天通过一个计算器的实例主要给大家
- 现在很多app的首页都有一个倒计时控件,比如说3秒或者5秒自动跳转界面,或者点击控件直接跳过首先,自定义控件CircleProgressba
- 目录为什么选择MQTTMQTT, 启动!使用方式Client模式创建工厂类创建工具类Spring Integration总结为什么选择MQT
- 本文实例为大家分享了Unity3D实现物体排成弧行的具体代码,供大家参考,具体内容如下一般用在Pico、HTC、DP等VR设备中效果:完整代
- 在任何的生产环境中我们都不可逃避并发这个问题,多线程作为并发问题的技术支持让我们不得不去了解。这一块知识就像一个大蛋糕一样等着我们去分享,抱
- 本文实例讲述了Java实现克隆的三种方式。分享给大家供大家参考,具体如下:1、浅复制(浅克隆)这种浅复制,其实也就是把被复制的这个对象的一些
- RocketMQ发送消息我们在使用RocketMQ发送消息时,一般都会使用DefaultMQProducer,类型的代码如下:Default
- 本文假设读者已经有一定Dagger2使用经验使用疑惑之前工作中一直在使用dagger2进行开发,用起来确实很爽,但是我从我第一次使用我就一直
- Spring Security和Shiro的区别相同点1、认证功能2、授权功能3、加密功能4、会话管理5、缓存支持6、rememberMe功