当前位置: 首页 > news >正文

Spring Bean初始化及@PostConstruc执行顺序

目录

1. Bean初始化执行顺序

2. 成员变量初始化顺序

2.1 普通Java类(非Spring环境)

(1) 默认初始化(即初始分配内存)

(2) 显式初始化

(3) 构造器初始化

(4)完整顺序

2.2 Spring管理的Bean(依赖注入场景)

(1) 普通成员变量

(2) 依赖注入的成员变量

(3) 生命周期回调的影响

(4)关键区别总结

2.3 final 成员变量 

2.4 常见面试问题


1. Bean初始化执行顺序

  1. 构造函数 - 首先调用Bean的构造函数

  2. 依赖注入 - 完成所有依赖项的注入(@Autowired等)

  3. @PostConstruct方法 - 执行带有@PostConstruct注解的方法

  4. InitializingBean的afterPropertiesSet() - 如果Bean实现了InitializingBean接口

  5. 自定义init方法 - 执行通过@Bean(initMethod="...")或XML配置中init-method指定的方法

@Component
public class ExampleBean implements InitializingBean {public ExampleBean() {System.out.println("1. 构造函数");}@Autowiredpublic void setDependency(SomeDependency dep) {System.out.println("2. 依赖注入");}@PostConstructpublic void postConstruct() {System.out.println("3. @PostConstruct方法");}@Overridepublic void afterPropertiesSet() {System.out.println("4. InitializingBean的afterPropertiesSet()");}@Bean(initMethod = "customInit")public void customInit() {System.out.println("5. 自定义init方法");}
}

2. 成员变量初始化顺序

在Java中,类的成员变量(非静态成员变量)的初始化时机取决于其定义方式(直接赋值、构造器赋值、初始化块等)以及是否涉及依赖注入(如Spring框架)。

2.1 普通Java类(非Spring环境)

成员变量的初始化顺序和时机如下:

(1) 默认初始化(即初始分配内存)

  • 时机:对象实例化时(new关键字调用构造器之前)。

  • 规则:所有成员变量先被赋予默认值(int0booleanfalse,引用类型→null等)。

(2) 显式初始化

  • 时机:紧随默认初始化之后,按代码中的声明顺序执行。

  • 方式

    • 直接赋值:

public class MyClass {private int a = 10;          // 显式赋值private String s = "hello";  // 显式赋值
}

  • 初始化块(代码块):
public class MyClass {private int x;{x = 20; // 初始化块赋值}
}

(3) 构造器初始化

  • 时机:在显式初始化之后,构造器最后执行。

  • 特点:构造器中的赋值会覆盖之前的默认值或显式赋值。

public class MyClass {private int value;public MyClass() {this.value = 30; // 构造器赋值}
}

(4)完整顺序

默认值 → 显式赋值/初始化块 → 构造器赋值


2.2 Spring管理的Bean(依赖注入场景)

在Spring中,成员变量的初始化分为依赖注入普通成员变量初始化两部分:

(1) 普通成员变量

  • 初始化规则与普通Java类一致(默认值 → 显式赋值 → 构造器)。

  • 示例

@Component
public class MyBean {private int count = 100;  // 显式赋值(Spring无关)public MyBean() {this.count = 200;     // 构造器覆盖}
}

(2) 依赖注入的成员变量

  • 时机:在Bean实例化后,由Spring容器通过反射或Setter方法注入。

    • 字段注入(@Autowired
      在构造器和显式赋值之后,通过反射直接注入。

      @Component
      public class MyBean {@Autowiredprivate Dependency dependency; // Spring在对象构造后注入
      }

    • 构造器注入
      在实例化时通过构造器参数注入(等同于普通Java的构造器赋值)。

      @Component
      public class MyBean {private final Dependency dependency;public MyBean(Dependency dependency) {this.dependency = dependency; // 构造时注入}
      }

(3) 生命周期回调的影响

  • @PostConstruct方法会在依赖注入完成后执行,此时所有成员变量(包括注入的依赖)已就绪:

    @Component
    public class MyBean {@Autowiredprivate Dependency dependency;@PostConstructpublic void init() {System.out.println(dependency); // 依赖已注入}
    }

(4)关键区别总结

场景成员变量初始化时机
普通Java类默认值 → 显式赋值/初始化块 → 构造器赋值
Spring Bean(字段注入)默认值 → 显式赋值 → 构造器 → 依赖注入 → @PostConstruct
Spring Bean(构造器注入)与普通Java类相同,依赖通过构造器参数传入

2.3 final 成员变量 

  • 必须声明时、初始化块或构造器中赋值,否则编译错误。

public class MyClass {private final int x = 10;  // 声明时赋值private final int y;{ y = 20; }  // 初始化块赋值private final int z;public MyClass() {z = 30;  // 构造器赋值}
}

2.4 常见面试问题

Q1: 为什么构造器里的赋值能覆盖显式赋值?

因为构造器是最后执行的,可以修改之前的值。

Q2: 以下代码的输出是什么?

public class Test {private int x = 10;{ x = 20; }public Test() {System.out.println(x);x = 30;}public static void main(String[] args) {new Test(); // 输出?}
}
--
答案:20(显式赋值和初始化块先执行,构造器最后执行)。

http://www.dtcms.com/a/294816.html

相关文章:

  • 零侵入加解密方案:Spring Boot + Jasypt + AOP实现敏感数据自动保护
  • Leetcode力扣解题记录--第54题(矩阵螺旋)
  • 表征工程中哪里用到内积 :内积vs余弦相似度--谁更胜一筹?
  • 智慧农业平台-农资农服农业数字化转型
  • 算法第三十七天:动态规划part05(第九章)
  • Golang各版本特性
  • 算法:数组part01:704. 二分查找 +977.有序数组的平方
  • ZeroMQ源码深度解析:高性能网络库的架构设计与性能优化
  • 高效编程革命:DeepSeek V3多语言支持与性能优化实战
  • 【前端】当前主流的 CSS 预处理器语言Sass / SCSS、Less、Stylus
  • C++:list(1)list的使用
  • HomeAssistant本地开发笔记
  • 「iOS」——KVO
  • MCP客户端架构与实施
  • SQL基础⑦ | 子查询
  • Linux——System V 共享内存 IPC
  • 【第十二章 W55MH32 NetBIOS示例标题】
  • ChatGPT桌面版深度解析
  • clientHeight(用于获取元素的可视高度)
  • 大致自定义文件I/O库函数的实现详解(了解即可)
  • 计算机网络学习----域名解析
  • uni-app平板端自定义样式合集
  • 【67】MFC入门到精通——MFC 销售管理系统 项目实现详细教程
  • 【自动化运维神器Ansible】深入解析Ansible Host-Pattern:精准控制目标主机的艺术
  • PowerShell自动化核对AD与HR系统账户信息实战指南
  • Hexo - 免费搭建个人博客02 - 创建个人博客
  • 智能办公如何创建e9流程
  • 力扣刷题(第九十六天)
  • Windows 用 Python3 快速搭建 HTTP 服务器
  • Google Chrome V8< 14.0.221 类型混淆漏洞