Spring干预Bean的生命周期的方法详解

 更新时间:2025年07月08日 08:27:26   作者:冰糖心书房  
Spring 提供了多种机制让我们能够在 Bean 生命周期的不同节点“插入”自己的逻辑,这些机制可以分为两大类:针对单个 Bean 的干预和针对所有/多个 Bean 的全局干预,本文将通过代码示例给大家详细的介绍一下,需要的朋友可以参考下

Spring 提供了多种机制让我们能够在 Bean 生命周期的不同节点“插入”自己的逻辑,这些机制可以分为两大类:针对单个 Bean 的干预针对所有/多个 Bean 的全局干预

一、 针对单个 Bean 的干预(最常用)

这些方法让你为一个特定的 Bean 类定义其初始化和销毁逻辑。

1. 使用 JSR-250 注解(推荐方式)

这是现在最优雅、也是 Spring 官方推荐的方式。它使用 Java 的标准注解,与 Spring 框架解耦。

  • @PostConstruct:在依赖注入完成之后,执行任何自定义的初始化逻辑。可以把它看作是 Bean 的“构造函数完成后的补充构造函数”。
  • @PreDestroy:在容器销毁 Bean 之前,执行清理工作。

示例:

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

@Service
public class DataProcessor {

    @Autowired
    private DataSource dataSource; // 依赖会被先注入

    private Connection connection;

    public DataProcessor() {
        System.out.println("1. 调用构造函数: dataSource is null? " + (dataSource == null));
    }

    @PostConstruct
    public void openConnection() {
        System.out.println("3. 执行 @PostConstruct: dataSource is null? " + (dataSource == null));
        System.out.println("正在打开数据库连接...");
        // 此时 dataSource 已经被注入,可以安全使用
        // this.connection = dataSource.getConnection(); 
    }

    public void process() {
        System.out.println("正在处理数据...");
    }

    @PreDestroy
    public void closeConnection() {
        System.out.println("执行 @PreDestroy: 正在关闭数据库连接...");
        // if (this.connection != null) this.connection.close();
    }
}

优点:代码简洁,与 Spring 解耦,符合 Java EE 规范。

2. 实现 Spring 的特定接口

这是 Spring 早期提供的方式,需要你的 Bean 类实现 Spring 框架的接口。

  • InitializingBean:实现它的 afterPropertiesSet() 方法,效果同 @PostConstruct
  • DisposableBean:实现它的 destroy() 方法,效果同 @PreDestroy

示例:

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

@Component
public class LegacyService implements InitializingBean, DisposableBean {

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("执行 InitializingBean.afterPropertiesSet()");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("执行 DisposableBean.destroy()");
    }
}

缺点:代码与 Spring 框架产生了强耦合,不推荐在新代码中使用。

3. 在配置中指定 init-method 和 destroy-method

这种方式完全将生命周期逻辑的调用与 Bean 类本身解耦。适用于你无法修改其源代码的第三方库 Bean。

XML 配置:

<bean id="myService" class="com.example.MyService" 
      init-method="customInit" 
      destroy-method="customCleanup"/>

Java 配置:

@Configuration
public class AppConfig {
    @Bean(initMethod = "customInit", destroyMethod = "customCleanup")
    public MyService myService() {
        return new MyService();
    }
}

优点:对类代码无侵入。

三者执行顺序@PostConstruct -> InitializingBean.afterPropertiesSet() -> init-method

二、 针对所有/多个 Bean 的全局干预(高级/框架级)

这些机制是 Spring 框架的强大武器,允许你对容器中所有(或部分)Bean 的生命周期进行统一的、批量的处理。

1. BeanPostProcessor(Bean 后置处理器)

这是最重要、最强大的全局干预接口。它像一个“质检员”,容器中每一个 Bean 在初始化前后都会经过它进行“检查”和“加工”。

它有两个核心方法:

  • postProcessBeforeInitialization(Object bean, String beanName):在任何 Bean 的初始化方法(如 @PostConstruct调用前执行。
  • postProcessAfterInitialization(Object bean, String beanName):在任何 Bean 的初始化方法调用后执行。

Spring 的 AOP(如 @Transactional)就是通过 BeanPostProcessor 实现的。它在 postProcessAfterInitialization 阶段检查 Bean,如果发现需要代理,就返回一个代理对象来替换原始的 Bean 实例。

示例: 创建一个打印所有 Bean 初始化信息的后置处理器。

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 {
        System.out.println("质检员[Before]: 正在检查 " + beanName);
        return bean; // 必须返回 bean,否则后续流程拿不到对象
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("质检员[After]: " + beanName + " 已完成初始化。");
        // 这里可以返回原始 bean,也可以返回一个包装后的代理 bean
        return bean;
    }
}

2. Aware 系列接口

Aware 接口的作用是让 Bean 能够“感知”并获取到它所在的容器环境资源。这发生在依赖注入之后,自定义初始化方法之前

  • BeanNameAware:让 Bean 知道它在容器中的 ID。
  • BeanFactoryAware:让 Bean 获取到创建它的 BeanFactory,从而可以编程方式地获取其他 Bean。
  • ApplicationContextAware:功能同上,但获取的是功能更强大的 ApplicationContext

示例:

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

@Component
public class AwareService implements ApplicationContextAware {

    private ApplicationContext context;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("AwareService 感知到了 ApplicationContext");
        this.context = applicationContext;
    }
    
    public void doSomething() {
        // 可以通过 context 手动获取其他 bean
        DataProcessor processor = context.getBean(DataProcessor.class);
        processor.process();
    }
}

注意:过度使用 Aware 接口会增加代码与 Spring 容器的耦合度,应谨慎使用。

总结

干预方式作用阶段影响范围推荐度/适用场景
@PostConstruct / @PreDestroy初始化后 / 销毁前单个 Bean强烈推荐,代码清晰,与框架解耦。
InitializingBean / DisposableBean初始化后 / 销毁前单个 Bean不推荐,与 Spring 强耦合,用于兼容老代码。
init-method / destroy-method初始化后 / 销毁前单个 Bean推荐,用于无法修改源码的第三方 Bean。
BeanPostProcessor初始化前后所有 Bean高级/框架级。用于实现 AOP、自定义注解处理等全局逻辑。
Aware 接口初始化前单个 Bean谨慎使用。当 Bean 需要主动与容器交互时使用。

简单来说,作为应用开发者,你的首选和绝大多数情况下的选择应该是 @PostConstruct@PreDestroy 如果你需要开发框架级别的功能,那么 BeanPostProcessor 则是你的核武器。

以上就是Spring干预Bean的生命周期的方法详解的详细内容,更多关于Spring干预Bean生命周期的资料请关注脚本之家其它相关文章!

相关文章

  • 如何解决redisTemplate注入为空问题

    如何解决redisTemplate注入为空问题

    这篇文章主要介绍了如何解决redisTemplate注入为空问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-07-07
  • Java中防止SQL注入和XSS攻击的处理指南

    Java中防止SQL注入和XSS攻击的处理指南

    在当今互联网时代,Web应用安全已成为开发者必须重视的核心问题,SQL注入和XSS攻击作为OWASP Top 10中的常见威胁,本文将深入探讨这两种攻击方式的原理,并提供Java开发中的实用防护方案
    2025-10-10
  • Java如何使用Query动态拼接SQL详解

    Java如何使用Query动态拼接SQL详解

    这篇文章主要给大家介绍了关于Java如何使用Query动态拼接SQL的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-01-01
  • SpringBoot通过Filter实现整个项目接口的SQL注入拦截详解

    SpringBoot通过Filter实现整个项目接口的SQL注入拦截详解

    这篇文章主要介绍了SpringBoot通过Filter实现整个项目接口的SQL注入拦截详解,SQL注入是比较常见的网络攻击方式之一,在客户端在向服务器发送请求的时候,sql命令通过表单提交或者url字符串拼接传递到后台持久层,最终达到欺骗服务器执行恶意的SQL命令,需要的朋友可以参考下
    2023-12-12
  • JAVA对象分析之偏向锁、轻量级锁、重量级锁升级过程

    JAVA对象分析之偏向锁、轻量级锁、重量级锁升级过程

    这篇文章主要介绍了JAVA对象分析之偏向锁、轻量级锁、重量级锁升级过程,又对这方面感兴趣的同学可以跟着一起研究下
    2021-02-02
  • Java线程优先级示例代码

    Java线程优先级示例代码

    使用过Bit下载软件的同学应该很清楚,我们有多个下载任务同时执行,而其中的某一个或多个是非常重要的,于是给这些任务设定一个高度优先,以便任务可以获取更多的带宽尽早完成下载
    2013-09-09
  • Spring注入bean的四种方式总结

    Spring注入bean的四种方式总结

    我们谈到Spring的时候一定会提到IOC容器、DI依赖注入,Spring通过将一个个类标注为Bean的方法注入到IOC容器中,达到了控制反转的效果,Spring帮我们实现了一种通过注解来实现注入的方法,所以本文为大家介绍了Spring注入bean的四种方式,需要的朋友可以参考下
    2025-11-11
  • 详解Java中的final关键字

    详解Java中的final关键字

    子类可以在父类的基础上改写父类内容,为了避免这种随意改写的情况,Java提供了final 关键字,用于修饰不可改变内容。本文就来详细说说final关键字的使用,需要的可以参考一下
    2022-10-10
  • Java代码重构的几种模式详解

    Java代码重构的几种模式详解

    这篇文章详细介绍了Java代码重构的几种模式,有需要的朋友可以参考一下
    2013-10-10
  • Java中的WebSocket与实时通信详解

    Java中的WebSocket与实时通信详解

    本文介绍WebSocket的概念、工作原理及Java中实现WebSocket的技术手段,包括JavaAPIforWebSocket(JSR356)和SpringWebSocket,通过实际应用场景(如即时聊天、实时通知、在线游戏)进行了详细分析,展示了WebSocket在现代Web应用中的重要性,感兴趣的朋友跟随小编一起看看吧
    2025-11-11

最新评论