总结Bean的三种自定义初始化和销毁方法

网友投稿 270 2022-08-31


总结Bean的三种自定义初始化和销毁方法

目录Bean三种自定义初始化和销毁一. 三种方法概述二. 方法详述spring初始化后获取自定义注解Bean一.新建注解类二.新建接口类三.实现接口ApplicationListener

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

BcBTfpWt 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 时BcBTfpWt的处理方法,它只有 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。。。初始化方法initCaBcBTfpWtrC()");

}

@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注解来定制执行顺序,越小越优先执行。


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Django(part5)--url匹配优先级
下一篇:Django(part3)--制作我的第一个网页(第一个django项目)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~