InitializingBean接口和@PostConstruct-笔记

1. InitializingBean 简介

1.1 功能简介

InitializingBean 是 Spring 框架中的一个接口,用在 Bean 初始化后执行自定义逻辑。它提供了 afterPropertiesSet() 方法,该方法在以下时机被 Spring 容器自动调用:

  1. 属性注入完成后(即所有通过 setter 方法或构造函数注入的属性已设置完毕)。
  2. Bean 初始化阶段的最后一步(在调用 @PostConstruct 注解的方法之后,如果同时存在的话)。

核心方法

  • void afterPropertiesSet():需要实现此方法以定义初始化逻辑。

1.2 用法演示

step1. 定义一个实现 InitializingBean 的 Bean

import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.InitializingBean;public class UserBean implements InitializingBean {private String name;// 属性注入需要 setter 方法public void setName(String name) {this.name = name;}// 实现 InitializingBean 接口的 afterPropertiesSet 方法@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("InitializingBean 的 afterPropertiesSet() 被调用。");System.out.println("用户名称: " + name);}
}

step2. Spring 配置类(Java 配置)

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class AppConfig {@Bean(name = "userBean")public UserBean userBean() {UserBean bean = new UserBean();bean.setName("John Doe"); // 通过 setter 注入属性return bean;}
}

step3. 启动 Spring 容器并测试

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class SpringDemo {public static void main(String[] args) {// 创建 Spring 应用上下文ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);// 获取 Bean(此时已触发初始化逻辑)UserBean userBean = context.getBean("userBean", UserBean.class);// 输出结果示例:// InitializingBean 的 afterPropertiesSet() 被调用。// 用户名称: John Doe}
}

2. @PostConstruct简介

2.1 功能简介

@PostConstruct 是 Java EE/Jakarta EE 中的一个注解(定义于 JSR-250 规范),用于标记一个方法在依赖注入完成后执行初始化操作。它通常与 Spring 框架一起使用,适用于需要在对象初始化时执行特定逻辑的场景。

核心功能

1. 初始化方法:标注的方法会在以下两个操作完成后被调用:

  • 依赖注入(DI)完成:Spring 容器完成对 Bean 的属性注入(如 @Autowired@Value 等)。
  • Bean 实例化:Bean 对象被创建后。

2. 执行时机: 是 Bean 生命周期中的一个关键步骤,通常在 @Autowired 或其他注入方式完成后执行,但早于 @PreDestroy 注解的销毁方法。

方法约束

  • 无参数且无返回值:被标注的方法必须是 void 类型且无参数。
@PostConstruct
public void init() { ... } // 正确
  • 不抛出受检异常:方法不能声明抛出受检异常(checked exception),否则会抛出 BeanCreationException
@PostConstruct
public void init() throws IOException { ... } // 错误!
  • 实例方法:只能标注在实例方法上,不能用于静态方法或字段。
  • 唯一性:一个 Bean 中只能有一个 @PostConstruct 方法,否则会引发冲突。

使用场景

  • 资源初始化:例如建立数据库连接、初始化缓存、加载配置等。
  • 依赖验证:检查注入的依赖是否合法。
  • 状态初始化:设置 Bean 的初始状态。

注意事项

  • 依赖必须注入完成:在 @PostConstruct 方法中,所有通过 @Autowired 等注入的依赖均已可用。
  • 执行顺序: 在以下步骤中触发:Bean 实例化 → 依赖注入 → @PostConstruct 方法 → BeanPostProcessor.postProcessAfterInitialization()

2.2 用法演示

import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;public class MyService {@Autowiredprivate MyRepository repository;@PostConstructpublic void init() {// 在依赖注入完成后执行的初始化逻辑System.out.println("Repository is initialized: " + repository);// 可在此处进行数据库连接或其他初始化操作}
}

3. InitializingBean 和 @PostConstruct 的对比分析

3.1 对比分析

对比维度@PostConstructInitializingBean
来源Java EE 标准注解(javax.annotation.PostConstruct)。Spring 框架接口(org.springframework.beans.factory.InitializingBean)。
执行时机属性注入完成后立即执行(在 InitializingBean 的 afterPropertiesSet() 之前)。属性注入完成后执行(在 @PostConstruct 之后)。
使用方式直接在方法上添加注解,无需实现接口。需要实现接口并重写 afterPropertiesSet() 方法。
依赖性需要引入 javax.annotation 依赖(Java 9+ 内置,低版本需手动添加)。无需额外依赖(Spring 自带)。
适用场景简单的初始化逻辑,且希望代码不依赖 Spring 特定接口。需要与 Spring 生命周期深度集成(如依赖 Spring 特定功能)或需兼容旧代码。
侵入性更简洁,无接口侵入。需实现接口,具有侵入性。

2. 代码演示:同时使用两者,验证执行顺序

step1: 定义一个同时使用 @PostConstruct 和 InitializingBean 的 Bean

import javax.annotation.PostConstruct;
import org.springframework.beans.factory.InitializingBean;public class MyBean implements InitializingBean {public MyBean() {System.out.println("构造函数被调用");}@PostConstructpublic void initByPostConstruct() {System.out.println("@PostConstruct 方法执行");}@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("InitializingBean.afterPropertiesSet() 执行");}
}

step2. Spring 配置类(Java 配置)

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class AppConfig {@Beanpublic MyBean myBean() {return new MyBean();}
}

step3. 启动 Spring 容器并观察输出

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class Main {public static void main(String[] args) {ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);// 输出顺序:// 1. 构造函数被调用// 2. @PostConstruct 方法执行// 3. InitializingBean.afterPropertiesSet() 执行}
}

输出结果:

构造函数被调用
@PostConstruct 方法执行
InitializingBean.afterPropertiesSet() 执行

关键点解释

  1. 执行顺序

    • @PostConstruct 的方法优先于 InitializingBean 的 afterPropertiesSet() 执行。
    • 这是因为 Spring 在初始化 Bean 时,会先处理注解(如 @PostConstruct),再触发接口定义的回调(如 InitializingBean)。
  2. 构造函数与初始化方法

    • 构造函数在 Bean 实例化时调用(属性未注入)。
    • 初始化方法(@PostConstruct 和 InitializingBean)在属性注入完成后调用

3.3 选择建议

根据场景选择

  • 推荐使用 @PostConstruct 的场景

    • 需要 简洁代码,避免实现接口。
    • 不依赖 Spring 特殊功能,仅需基础初始化逻辑。
    • 需要在 更早阶段 执行初始化(如依赖注入后立即初始化资源)。
  • 推荐使用 InitializingBean 的场景

    • 需要与 Spring 的生命周期深度集成(例如访问 Spring 上下文)。
    • 项目已有大量使用 InitializingBean 的代码,无需迁移成本。
    • 需要分阶段执行初始化逻辑(如先 @PostConstruct 处理基础逻辑,再通过 InitializingBean 执行 Spring 特定逻辑)。

总结

  • @PostConstruct 是更现代、简洁的选择,且与 Spring 无关(可跨框架使用),适合大多数场景。可视为在 Spring 中用于替代 InitializingBean 接口或 XML 配置的初始化方法,简化代码并提高可读性。
  • InitializingBean 适合需要与 Spring 生命周期深度耦合的情况。但需实现接口,侵入性较强,优先使用@PostConstruct
  • 若同时使用两者,需注意执行顺序并合理规划逻辑分阶段。

3.4 其他替代选择

SpringBoot启动后自动执行方法的各种方式-笔记-CSDN博客

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《代码整洁之道》第9章 单元测试 - 笔记

测试驱动开发 (TDD) 是一种编写整洁代码的“规程”或“方法论”,而不仅仅是测试技术。 JaCoCo 在运行测试后生成详细的覆盖率报告的工具, maven 引用。 测试驱动开发 测试驱动开发(TDD)是什么? TDD 不是说写完代码…

openGauss新特性 | DataKit支持PostgreSQL到openGauss的迁移能力

Postgresql-\>openGauss迁移工具debezium-connector-postgres 可获得性 本特性自openGauss 7.0.0-RC1版本开始引入。 特性简介 debezium-connector-postgres工具是一个基于Java语言的Postgresql到openGauss的复制工具。该工具提供了初始全量数据及对象(视图、…

在MySQL Shell里 重启MySQL 8.4实例

前一段时间看到MySQL官方视频的Oracle工程师在mysql shell里面重启mysql实例,感觉这个操作很方便,所以来试试,下面为该工程师的操作截图 1.MySQL Shell 通过root用户连上mysql,shutdown mysql实例 [rootmysql8_3 bin]# mysqlshMy…

truffle

文章目录 truffle目录结构各文件作用在本地测试合约 truffle 项目来自https://github.com/Dapp-Learning-DAO/Dapp-Learning/blob/main/basic/04-web3js-truffle/README-CN.md Truffle 是基于 Solidity 语言的一套开发框架,它简化了去中心化应用(Dapp&…

SpringCloud核心组件Eureka菜鸟教程

关于Spring Cloud Eureka的核心概念 Eureka 是 Netflix 开源的一款基于 REST 的服务发现工具,主要用于中间层服务器的云端负载均衡。它通过维护一个服务注册表来实现服务之间的通信1。在 Spring Cloud 中,Eureka 提供了一个高可用的服务注册与发现机制&a…

职业教育新形态数字教材的建设与应用:重构教育生态的数字化革命

教育部新时代职业学校名师(名匠)名校长培养计划专题 四川省第四批职业学校名师(名匠)培养计划专题 在某职业院校的智能制造课堂上,学生佩戴VR设备,通过数字教材中的虚拟工厂完成设备装配训练,系统实时生成操作评分与改进建议。这一场景折射出…

基于Python的携程国际机票价格抓取与分析

一、项目背景与目标 携程作为中国领先的在线旅行服务平台,提供了丰富的机票预订服务。其国际机票价格受多种因素影响,包括季节、节假日、航班时刻等。通过抓取携程国际机票价格数据,我们可以进行价格趋势分析、性价比评估以及旅行规划建议等…

Windows 图形显示驱动开发-初始化WDDM 1.2 和 PnP

(WDDM) 1.2 及更高版本显示微型端口驱动程序的所有 Windows 显示驱动程序都必须支持以下行为,以响应即插即用 (PnP) 基础结构启动和停止请求。 根据驱动程序返回成功或失败代码,或者系统硬件是基于基本输入/输出系统 (BIOS) 还是统一可扩展固件接口 (UEF…

【1区SCI】Fusion entropy融合熵,多尺度,复合多尺度、时移多尺度、层次 + 故障识别、诊断-matlab代码

引言 2024年9月,研究者在数学领域国际顶级SCI期刊《Chaos, Solitons & Fractals》(JCR 1区,中科院1区 Top)上以“Fusion entropy and its spatial post-multiscale version: Methodology and application”为题发表最新科学研…

高并发架构设计之缓存

一、引言 缓存技术作为高并发架构设计的基石之一,通过数据暂存和快速访问机制,在提升系统性能、降低后端负载方面发挥着不可替代的作用。优秀的缓存设计能够将系统吞吐量提升数个数量级,将响应时间从秒级降至毫秒级,甚至成为系统…

Unity AI-使用Ollama本地大语言模型运行框架运行本地Deepseek等模型实现聊天对话(一)

一、Ollama介绍 官方网页:Ollama官方网址 中文文档参考:Ollama中文文档 相关教程:Ollama教程 Ollama 是一个开源的工具,旨在简化大型语言模型(LLM)在本地计算机上的运行和管理。它允许用户无需复杂的配置…

Docker Python 镜像使用指南

1. 使用 Python 镜像创建容器 docker run -itd -v /data:/data python:latest 作用:创建一个基于 python:latest 镜像的容器,并后台运行。 参数说明: -itd:交互式后台运行(-i 交互模式,-t 分配伪终端&…

matlab中Simscape的调用-入门

Simscape 是由 MathWorks 公司开发的一款基于物理建模的仿真工具,它建立在 MATLAB/Simulink 平台之上,专门用于建模和仿真多领域物理系统。 主要特点 多领域建模:Simscape 提供了丰富的物理元件库,涵盖了机械、电气、液压、气动…

Flowable7.x学习笔记(十三)查看部署流程图

前言 Flowable 的流程图是 Flowable Modeler 或 Process Editor 中,使用拖拽和属性面板基于 BPMN 2.0 元素(如任务、网关、事件、序列流等)渲染出的业务流程图形界面​。 一、将图形导出可查看的作用 ① 可视化建模 帮助业务分析师和开发者…

Bootstrap 模态框

Bootstrap 模态框 Bootstrap 模态框(Modal)是 Bootstrap 框架中的一个组件,它允许你在一个页面中创建一个模态对话框,用于显示内容、表单、图像或其他信息。模态框通常覆盖在当前页面上,提供了一种不离开当前页面的交…

python-69-基于graphviz可视化软件生成流程图

文章目录 1 Graphviz可视化软件1.1 graphviz简介1.2 安装部署2 基于python示例应用2.1 基本示例2.2 解决中文显示乱码2.3 显示多个输出边2.4 显示输出引脚名称2.5 从左至右显示布局2.6 设置节点为方形3 参考附录1 Graphviz可视化软件 1.1 graphviz简介 Graphviz(Graph Visua…

AJAX 介绍

一、什么是AJAX ? AJAX 是 异步的 JavaScript 和 XML(Asynchronous JavaScript And XML) 的缩写,是一种实现浏览器与服务器进行数据通信的技术。其核心是通过 XMLHttpRequest 对象在不重新刷新页面的前提下,与服务器交换数据并更…

新ubuntu物理机开启ipv6让外网访问

Ubuntu 物理机 SSH 远程连接与 IPv6 外网访问测试指南 1. 通过 SSH 远程连接 Ubuntu 物理机 1.1 安装 SSH 服务 sudo apt update sudo apt install openssh-server1.2 检查 SSH 服务状态 sudo systemctl status ssh确认出现 active (running)。 1.3 获取物理机 IP 地址 i…

linux系统上使用nginx访问php文件返回File not found错误处理方案

linux系统上使用nginx访问php文件返回File not found错误处理方案 第一种情况第二种情况 第一种情况 可以在你的location php 里面添加当文件不存在时返回404而不是交给php-fpm进行处理 location ~ \.php$ { ... #文件不存在转404 try_files $uri 404; ... }然后&#xff0c…

基于 SpringBoot 与 Redis 的缓存预热案例

文章目录 “缓存预热” 是什么?项目环境搭建创建数据访问层预热数据到 Redis 中创建缓存服务类测试缓存预热 “缓存预热” 是什么? 缓存预热是一种优化策略,在系统启动或者流量高峰来临之前,将一些经常访问的数据提前加载到缓存中…