@Bean 控制 Spring Bean 生命周期

1.基本用法

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AppConfig {
    @Bean(initMethod = "init", destroyMethod = "destroy")
    public MyService myService() {
        return new MyService();
    }
}
public class MyService {
    public void init() {
        // 在此添加初始化逻辑,例如资源的初始化、建立数据库连接等
        System.out.println("MyService 正在初始化...");
    }

    public void destroy() {
        // 在此添加销毁逻辑,例如关闭资源、释放数据库连接等
        System.out.println("MyService 正在销毁...");
    }
}

在上述代码中,@Configuration 注解的 AppConfig 类用于定义 Spring 的配置。

@Bean(initMethod = "init", destroyMethod = "destroy") 告诉 Spring 在创建 MyService Bean 时调用 init 方法进行初始化,在销毁 MyService Bean 时调用 destroy 方法进行清理。

可以在 init 方法中执行一些初始化操作,比如加载配置文件、创建连接、启动服务等。

在 destroy 方法中可以进行一些清理操作,比如关闭连接、释放资源、停止服务等。

2.更复杂的初始化和销毁逻辑

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@Configuration
public class AppConfig {
    @Bean
    public ExecutorService executorService() {
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        return executorService;
    }

    @Bean(destroyMethod = "shutdown")
    public ExecutorService managedExecutorService() {
        return Executors.newFixedThreadPool(5);
    }
}
  • 对于 executorService Bean,没有指定 destroyMethod,因为 Spring 会自动检测并调用 ExecutorService 的 shutdown 方法进行销毁。
  • 对于 managedExecutorService Bean,明确指定了 destroyMethod = "shutdown",确保 Spring 会调用 shutdown 方法关闭线程池。

这种方式允许你对不同的资源进行不同级别的控制,对于一些需要特殊处理的资源,可以显式指定销毁方法,而对于一些遵循 Java 标准的资源,Spring 可以自动处理。

3.结合其他 Spring 特性

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.beans.factory.annotation.Value;
import java.io.File;

@Configuration
public class AppConfig {
    @Value("${app.file.path}")
    private String filePath;

    @Bean(initMethod = "init", destroyMethod = "destroy")
    public File fileHandler() {
        return new File(filePath);
    }
}
public class File {
    private String filePath;

    public File(String filePath) {
        this.filePath = filePath;
    }

    public void init() {
        // 在此根据文件路径进行初始化操作,例如创建文件或检查文件是否存在等
        System.out.println("正在初始化文件处理器,文件路径: " + filePath);
    }

    public void destroy() {
        // 在此进行文件资源的清理,例如关闭文件流等
        System.out.println("正在销毁文件处理器");
    }
}

在这个例子中,@Value("${app.file.path}") 从配置文件中读取文件路径。

@Bean(initMethod = "init", destroyMethod = "destroy") 用于控制 File 类的生命周期。

在 init 方法中,可以根据文件路径进行一些操作,比如创建文件、打开文件流等。

在 destroy 方法中,可以进行一些清理操作,如关闭文件流、释放文件锁等。

4.与条件化 Bean 结合使用

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AppConfig {
    @Bean
    @Conditional(MyCondition.class)
    public MyService conditionalMyService() {
        return new MyService();
    }
}
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;

public class MyCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        // 根据条件判断是否创建 Bean
        return true;
    }
}

@Conditional(MyCondition.class) 可以根据条件决定是否创建 MyService Bean。

可以将 @Bean 注解与条件化 Bean 结合使用,在创建 Bean 时进行条件判断,并且可以结合生命周期控制,确保只有在满足条件时才创建并控制该 Bean 的生命周期。

5.优势和注意事项

使用 @Bean 注解可以在 Spring 中对 Bean 的生命周期进行有效的控制,通过指定初始化和销毁方法,可以确保资源的正确管理和程序的健壮性。根据不同的业务需求和资源类型,可以灵活运用 @Bean 注解及其相关特性。

优势:

@Bean 注解提供了一种灵活的方式来控制 Bean 的生命周期,尤其是对于第三方库或无法修改源代码的类,可以通过 initMethod 和 destroyMethod 来添加初始化和销毁逻辑。

可以结合 Spring 的其他特性,如 @Value 进行属性注入,@Conditional 进行条件化创建等,增强了配置的灵活性和可扩展性。

注意事项:

确保 initMethod 和 destroyMethod 中执行的操作是安全的,避免在这些方法中抛出异常,以免影响整个 Spring 容器的稳定性。

对于一些资源密集型的操作,如打开文件、建立数据库连接,要确保在 destroyMethod 中正确释放资源,防止资源泄漏。

6.除 @Bean 外控制 Bean 生命周期的方式

6.1实现 InitializingBean 和 DisposableBean 接口

import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;

@Component
public class MyComponent implements InitializingBean, DisposableBean {

    @Override
    public void afterPropertiesSet() throws Exception {
        // 该方法会在 Bean 的属性设置完成后被调用,可用于执行初始化操作
        System.out.println("MyComponent is being initialized (InitializingBean)");
    }

    @Override
    public void destroy() throws Exception {
        // 该方法会在 Bean 销毁时被调用,可用于执行资源释放等操作
        System.out.println("MyComponent is being destroyed (DisposableBean)");
    }
}

InitializingBean 接口包含 afterPropertiesSet() 方法,它会在 Spring 容器完成 Bean 的属性设置后被调用,可用于执行一些初始化操作,如建立数据库连接、初始化缓存等。

DisposableBean 接口包含 destroy() 方法,它会在 Spring 容器销毁 Bean 时调用,适合执行一些清理操作,如关闭文件、释放数据库连接等。

6.2使用 JSR-250 注解:@PostConstruct 和 @PreDestroy

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import org.springframework.stereotype.Component;

@Component
public class MyComponent {

    @PostConstruct
    public void init() {
        // 该方法会在 Bean 的构造函数和属性注入完成后被调用,用于初始化操作
        System.out.println("MyComponent is being initialized (@PostConstruct)");
    }

    @PreDestroy
    public void cleanup() {
        // 该方法会在 Bean 销毁前被调用,用于清理操作
        System.out.println("MyComponent is being destroyed (@PreDestroy)");
    }
}

@PostConstruct 注解标记的方法会在 Bean 的构造函数和属性注入完成后调用,可进行一些初始化工作,如启动后台线程、加载配置等。

@PreDestroy 注解标记的方法会在 Bean 销毁前调用,可用于资源释放,如关闭线程池、清理临时文件等。

6.3自定义初始化和销毁方法

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;

@Component
public class MyComponent {

    @Autowired
    public void customInit() {
        // 自定义的初始化方法,可以通过 @Autowired 等注入依赖,在属性注入后执行
        System.out.println("MyComponent is being initialized (custom init)");
    }

    public void customDestroy() {
        // 自定义的销毁方法,可用于资源释放等操作
        System.out.println("MyComponent is being destroyed (custom destroy)");
    }
}

可以在 Bean 中定义自定义的初始化和销毁方法,Spring 可以通过方法名约定或配置来调用它们。

对于自定义的初始化方法,还可以利用 @Autowired 等注解注入依赖,在属性注入完成后进行初始化操作。

6.4 BeanPostProcessor 接口

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;

@Component
public class MyBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof MyComponent) {
            System.out.println("Before initialization of MyComponent");
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof MyComponent) {
            System.out.println("After initialization of MyComponent");
        }
        return bean;
    }
}

BeanPostProcessor 接口允许你在 Bean 的初始化前后插入自定义逻辑。

postProcessBeforeInitialization 方法会在 Bean 初始化之前调用,可用于前置处理,如修改 Bean 的属性、检查 Bean 的状态等。

postProcessAfterInitialization 方法会在 Bean 初始化之后调用,可用于后置处理,如添加代理、包装 Bean 等。

6.5基于 XML 配置的方式

<beans>
    <bean id="myComponent" class="com.example.MyComponent" init-method="init" destroy-method="cleanup">
        <!-- 配置 Bean 的属性等 -->
    </bean>
</beans>

在 XML 配置中,可以使用 init-method 属性指定 Bean 的初始化方法,destroy-method 属性指定 Bean 的销毁方法。

这种方式适用于传统的 Spring 配置,对于不使用 Java 配置的项目仍然很有用。

这些不同的方式提供了丰富的手段来控制 Bean 的生命周期,你可以根据具体情况选择最适合的方法。

例如,对于标准的 Spring 组件,使用 @PostConstruct 和 @PreDestroy 可能更方便;对于需要更细粒度控制或需要处理第三方类的情况,BeanPostProcessor 或 @Bean 注解的方法属性可能更合适;对于遵循传统的 XML 配置的项目,可使用 XML 中的 init-method 和 destroy-method

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/956622.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

农业农村大数据应用场景|珈和科技“数字乡村一张图”解决方案

近年来&#xff0c;珈和科技持续深耕农业领域&#xff0c;聚焦时空数据服务智慧农业。 珈和利用遥感大数据、云计算、移动互联网、物联网、人工智能等先进技术&#xff0c;搭建“天空地一体化”监测体系&#xff0c;并创新建设了150的全球领先算法模型&#xff0c;广泛应用于高…

综述:大语言模型在机器人导航中的最新进展!

简介 机器人导航是指机器人能够在环境中自主移动和定位的能力。本文系统地回顾了基于大语言模型&#xff08;LLMs&#xff09;的机器人导航研究&#xff0c;将其分为感知、规划、控制、交互和协调等方面。具体来说&#xff0c;机器人导航通常被视为一个几何映射和规划问题&…

[数据结构与算法]js实现二叉树

DFS 与 BFS dfs 递归 本质通过栈结构 bfs 层序遍历 通过队列结构 function permute(nums) {let res [];let cur []; // 记录当前内容let visted {}; //记录访问过的节点let len nums.length;function dfs(nth) {//递归终止条件if (nth len) {res.push([...cur]);return …

w167医院后台管理系统设计与实现

&#x1f64a;作者简介&#xff1a;多年一线开发工作经验&#xff0c;原创团队&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的网站项目。 代码可以查看文章末尾⬇️联系方式获取&#xff0c;记得注明来意哦~&#x1f339;赠送计算机毕业设计600个选题excel文…

K8S 容器重启策略

今天我们来实验容器重启策略。官网描述如下&#xff1a; Pod 的 spec 中包含一个 restartPolicy 字段&#xff0c;其可能取值包括 Always、OnFailure 和 Never。默认值是 Always。 Pod 的重启策略&#xff08;restartPolicy&#xff09;应用于 Pod 中的 应用容器&#xff08;也…

ROS机器人学习和研究的势-道-术-转型和变革的长期主义习惯

知易行难。说说容易做到难。 例如&#xff0c;不受成败评价影响&#xff0c;坚持做一件事情10年以上&#xff0c;专注事情本身。 机器人专业不合格且失败讲师如何让内心保持充盈的正能量&#xff08;节选&#xff09;-CSDN博客 时间积累 注册20年。 创作历程10年。 创作10年…

通过学习更多样化的生成数据进行更广泛的数据分发来改进实例分割

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 本次使用的英文整理的一些记录&#xff0c;练习一下为后续SCI发表论文打好基础 Improving Instance Segmentation by Learning Wider Data Distribution with More Diverse Generative Data Abstract In…

python编程-OpenCV(图像读写-图像处理-图像滤波-角点检测-边缘检测)角点检测

角点检测&#xff08;Corner Detection&#xff09;是计算机视觉和图像处理中重要的步骤&#xff0c;主要用于提取图像中的关键特征&#xff0c;以便进行后续的任务&#xff0c;比如图像匹配、物体识别、运动跟踪等。下面介绍几种常用的角点检测方法及其应用。 1. Harris角点检…

Git实用指南:忽略文件、命令别名、版本控制、撤销修改与标签管理

目录 1.忽略特殊文件 1.1.那如何配置我们需要忽略的文件的呢&#xff1f; 1.2.如何检验效果&#xff1f; 2.给命令配置别名 3.基本操作之版本回退 3.1.使用场景&#xff1a; 3.2.使用方法&#xff1a; 4.撤销修改 情况一&#xff1a;对于工作区的代码&#xff0c;还没…

Linux的基本指令(上) -- 0基础入门

目录 知识点引入 基本指令 ls指令 pwd 命令 cd 指令 touch 指令 stat指令 mkdir 指令 tree指令 rmdir 指令 rm 命令 man 指令 which 指令 alias 指令 echo指令 输出重定向: > 追加重定向&#xff1a;>> cp 指令 知识点引入 1. Linux中路径用 / 作为路径分隔…

论文阅读:CosAE Learnable Fourier Series for Image Restoration

这是 2024 NeurIPS 上发表的一篇文章&#xff0c;介绍了一种新型的基于傅里叶级数的通用编码器。 Abstract 本文介绍了余弦自动编码器&#xff08;Cosine Autoencoder, CosAE&#xff09;&#xff0c;这是一种新颖的通用自动编码器&#xff0c;它将经典傅里叶级数与前馈神经网…

网络编程-UDP套接字

文章目录 UDP/TCP协议简介两种协议的联系与区别Socket是什么 UDP的SocketAPIDatagramSocketDatagramPacket 使用UDP模拟通信服务器端客户端测试 完整测试代码 UDP/TCP协议简介 两种协议的联系与区别 TCP和UDP其实是传输层的两个协议的内容, 差别非常大, 对于我们的Java来说, …

【华为路由/交换机的ssh远程设置】

华为路由/交换机的ssh远程设置 R1&#xff08;client&#xff09;&#xff1a;10.1.1.1 R2&#xff08;server&#xff09;&#xff1a;10.1.1.2 R2服务端配置&#xff1a; 生成本机密钥 查看生成的密钥 设置AAA授权验证方式&#xff0c;并设置支持SSH协议 创建本地用户&…

计算机毕业设计PySpark+Hadoop+Hive机票预测 飞机票航班数据分析可视化大屏 航班预测系统 机票爬虫 飞机票推荐系统 大数据毕业设计

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

CSS笔记基础篇01——选择器、文字控制属性、背景属性、显示模式、盒子模型

黑马程序员视频地址&#xff1a; 前端Web开发HTML5CSS3移动web视频教程https://www.bilibili.com/video/BV1kM4y127Li?vd_source0a2d366696f87e241adc64419bf12cab&spm_id_from333.788.videopod.episodeshttps://www.bilibili.com/video/BV1kM4y127Li?vd_source0a2d3666…

C++学习第五天

创作过程中难免有不足&#xff0c;若您发现本文内容有误&#xff0c;恳请不吝赐教。 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、构造函数 问题1 关于编译器生成的默认成员函数&#xff0c;很多童鞋会有疑惑&#xff1a;不实现构造函数的情况下…

2024嵌入式系统的未来发展与技术洞察分享

时间如白驹过隙&#xff0c;不知不觉又是一年&#xff0c;这一年收获满满。接下来&#xff0c;将本年度对技术的感悟和洞察分析如下&#xff0c;希望对大家有所帮助。 在过去几十年里&#xff0c;嵌入式系统技术迅速发展&#xff0c;成为现代电子设备和智能硬件的核心组成部分。…

01设计模式(D3_设计模式类型 - D3_行为型模式)

目录 一、模版方法模式 1. 基本介绍 2. 应用案例一&#xff1a;豆浆制作问题 需求 代码实现 模板方法模式的钩子方法 3. View的draw&#xff08;Android&#xff09; Android中View的draw方法就是使用了模板方法模式 模板方法模式在 Spring 框架应用的源码分析 知识小…

Linux 中如何使用 inotify-tools 监控目录变化 ?

当 Linux 系统目录中有新文件创建时执行命令&#xff0c;可以通过组合使用工具和脚本实现监控。一种常见的方法是使用 inotify-tools&#xff0c;这是一个允许您监视文件系统事件的实用程序&#xff0c;与 shell 脚本一起使用。 Step 1: 安装 inotify-tools 首先&#xff0c;…

vid2vid-zero:使用Stable Diffusion进行零样本视频编辑

Paper: Wang W, Jiang Y, Xie K, et al. Zero-shot video editing using off-the-shelf image diffusion models[J]. arXiv preprint arXiv:2303.17599, 2023. Introduction: Unreleased Code: https://github.com/baaivision/vid2vid-zero 目录 一. 预备知识1. diffusion 引导…