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

 更新时间:2022年01月28日 14:36:04   作者:zijikanwa  
这篇文章主要介绍了Bean的三种自定义初始化和销毁方法,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

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

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • 一文精通Java中的volatile关键字

    一文精通Java中的volatile关键字

    volatile是java中的关键词之一,这篇文章主要给大家介绍了关于Java中volatile关键字的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用Java具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-05-05
  • Mybatis中一对多(collection)和一对一(association)的组合查询使用

    Mybatis中一对多(collection)和一对一(association)的组合查询使用

    这篇文章主要介绍了Mybatis中一对多(collection)和一对一(association)的组合查询使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-12-12
  • java rocketmq--消息的产生(普通消息)

    java rocketmq--消息的产生(普通消息)

    这篇文章主要介绍了java rocketmq--消息的产生(普通消息),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,,需要的朋友可以参考下
    2019-06-06
  • 关于springboot中nacos动态路由的配置

    关于springboot中nacos动态路由的配置

    这篇文章主要介绍了springboot中nacos动态路由的配置方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-09-09
  • SSH框架网上商城项目第4战之EasyUI菜单的实现

    SSH框架网上商城项目第4战之EasyUI菜单的实现

    SSH框架网上商城项目第4战之EasyUI菜单的实现,本文主要使用EasyUI技术简单实现后台菜单,感兴趣的小伙伴们可以参考一下
    2016-05-05
  • Springboot 接收POST、json、文本数据的方法 附示例

    Springboot 接收POST、json、文本数据的方法 附示例

    这篇文章主要介绍了Springboot 接收POST、json、文本数据实践,如果把 json 作为参数传递,我们可以使用 @requestbody 接收参数,将数据直接转换成对象,本文通过示例代码介绍的非常详细,需要的朋友可以参考下
    2023-10-10
  • Spring Jpa多数据源工程配置过程解析

    Spring Jpa多数据源工程配置过程解析

    这篇文章主要介绍了Spring Jpa多数据源工程配置过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-08-08
  • SpringBoot异步调用方法并接收返回值

    SpringBoot异步调用方法并接收返回值

    这篇文章主要为大家详细介绍了SpringBoot异步调用方法并接收返回值,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-09-09
  • Java 利用binarySearch实现抽奖计算逻辑

    Java 利用binarySearch实现抽奖计算逻辑

    这篇文章主要介绍了Java 利用binarySearch实现抽奖计算逻辑,帮助大家更好的理解和使用Java,感兴趣的朋友可以了解下
    2020-12-12
  • Spring AOP + 注解实现统一注解功能

    Spring AOP + 注解实现统一注解功能

    本文我们通过Spring AOP和Java的自定义注解来实现日志的插入功能,非常不错,具有一定的参考借鉴价值,需要的朋友一起看看吧
    2018-05-05

最新评论