Spring Bean初始化及@PostConstruc执行顺序示例详解

2025-07-24 20:50

本文主要是介绍Spring Bean初始化及@PostConstruc执行顺序示例详解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

《SpringBean初始化及@PostConstruc执行顺序示例详解》本文给大家介绍SpringBean初始化及@PostConstruc执行顺序,本文通过实例代码给大家介绍的非常详细,对大家的...

1. Bean初始化执行顺序

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

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

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

  4. InitializingBean的afterPropertiesSet() - 如果Bean实现了InitializingBeanhttp://www.chinasem.cn接口

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

@Component
public class ExampleBean implements InitializingBean {
    public ExampleBean() {
        System.out.println("1. 构造函数");
    }
    @Autowired
    public void setDependency(SomeDependency dep) {
   js     System.out.println("2. 依赖注入");
    }
    @PostConstruct
    public void postConstruct() {
        System.out.println("3. @PostksydNXmRConstruct方法");
    }
    @Override
    public 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 {
          @Autowired
          private 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 {
        @Autowired
        private Dependency dependency;
        @PostConstruct
        public 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(显式赋值和初始化块先执行,构造器China编程最后执行)。

到此这篇关于Spring Bean初始化及@PostConstruc执行顺序的文章就介绍到这了,更多相关Spring Bean初始化内容请搜索编程China编程(www.chinasem.cn)以前的文章或继续浏览下面的相关文章希望大家以后多多支持China编程(www.chinasem.cn)!

这篇关于Spring Bean初始化及@PostConstruc执行顺序示例详解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1155472

相关文章

go动态限制并发数量的实现示例

《go动态限制并发数量的实现示例》本文主要介绍了Go并发控制方法,通过带缓冲通道和第三方库实现并发数量限制,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面... 目录带有缓冲大小的通道使用第三方库其他控制并发的方法因为go从语言层面支持并发,所以面试百分百会问到

PyTorch中的词嵌入层(nn.Embedding)详解与实战应用示例

《PyTorch中的词嵌入层(nn.Embedding)详解与实战应用示例》词嵌入解决NLP维度灾难,捕捉语义关系,PyTorch的nn.Embedding模块提供灵活实现,支持参数配置、预训练及变长... 目录一、词嵌入(Word Embedding)简介为什么需要词嵌入?二、PyTorch中的nn.Em

Python Web框架Flask、Streamlit、FastAPI示例详解

《PythonWeb框架Flask、Streamlit、FastAPI示例详解》本文对比分析了Flask、Streamlit和FastAPI三大PythonWeb框架:Flask轻量灵活适合传统应用... 目录概述Flask详解Flask简介安装和基础配置核心概念路由和视图模板系统数据库集成实际示例Stre

Spring Boot 中的默认异常处理机制及执行流程

《SpringBoot中的默认异常处理机制及执行流程》SpringBoot内置BasicErrorController,自动处理异常并生成HTML/JSON响应,支持自定义错误路径、配置及扩展,如... 目录Spring Boot 异常处理机制详解默认错误页面功能自动异常转换机制错误属性配置选项默认错误处理

java如何实现高并发场景下三级缓存的数据一致性

《java如何实现高并发场景下三级缓存的数据一致性》这篇文章主要为大家详细介绍了java如何实现高并发场景下三级缓存的数据一致性,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 下面代码是一个使用Java和Redisson实现的三级缓存服务,主要功能包括:1.缓存结构:本地缓存:使

Java Spring的依赖注入理解及@Autowired用法示例详解

《JavaSpring的依赖注入理解及@Autowired用法示例详解》文章介绍了Spring依赖注入(DI)的概念、三种实现方式(构造器、Setter、字段注入),区分了@Autowired(注入... 目录一、什么是依赖注入(DI)?1. 定义2. 举个例子二、依赖注入的几种方式1. 构造器注入(Con

SpringBoot 异常处理/自定义格式校验的问题实例详解

《SpringBoot异常处理/自定义格式校验的问题实例详解》文章探讨SpringBoot中自定义注解校验问题,区分参数级与类级约束触发的异常类型,建议通过@RestControllerAdvice... 目录1. 问题简要描述2. 异常触发1) 参数级别约束2) 类级别约束3. 异常处理1) 字段级别约束

mybatis中resultMap的association及collectio的使用详解

《mybatis中resultMap的association及collectio的使用详解》MyBatis的resultMap定义数据库结果到Java对象的映射规则,包含id、type等属性,子元素需... 目录1.reusltmap的说明2.association的使用3.collection的使用4.总

详解MySQL中JSON数据类型用法及与传统JSON字符串对比

《详解MySQL中JSON数据类型用法及与传统JSON字符串对比》MySQL从5.7版本开始引入了JSON数据类型,专门用于存储JSON格式的数据,本文将为大家简单介绍一下MySQL中JSON数据类型... 目录前言基本用法jsON数据类型 vs 传统JSON字符串1. 存储方式2. 查询方式对比3. 索引

如何在Java Spring实现异步执行(详细篇)

《如何在JavaSpring实现异步执行(详细篇)》Spring框架通过@Async、Executor等实现异步执行,提升系统性能与响应速度,支持自定义线程池管理并发,本文给大家介绍如何在Sprin... 目录前言1. 使用 @Async 实现异步执行1.1 启用异步执行支持1.2 创建异步方法1.3 调用