最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring Bean初始化的三種常用方式(易懂版)

 更新時間:2025年12月02日 09:11:54   作者:碼刀攻城  
在Spring框架開發(fā)中,Bean的生命周期管理是核心基礎知識點,而Bean初始化作為生命周期中的關鍵環(huán)節(jié),負責在Bean實例創(chuàng)建并完成依賴注入后,執(zhí)行資源加載、參數配置、緩存初始化等核心業(yè)務邏輯,本文將詳細拆解Spring中3種主流的Bean初始化方式,需要的朋友可以參考下

引言

在Spring框架開發(fā)中,Bean的生命周期管理是核心基礎知識點,而Bean初始化作為生命周期中的關鍵環(huán)節(jié),負責在Bean實例創(chuàng)建并完成依賴注入后,執(zhí)行資源加載、參數配置、緩存初始化等核心業(yè)務邏輯。本文將從“是什么-怎么用-為什么”的角度,詳細拆解Spring中3種主流的Bean初始化方式,每種方式均提供完整可運行的代碼示例,并補充執(zhí)行順序驗證、場景對比及實戰(zhàn)注意事項,幫助新手快速掌握并靈活運用。

核心前提:Bean初始化的觸發(fā)時機——Spring容器創(chuàng)建Bean實例 → 完成所有屬性的依賴注入(如@Autowired、構造器注入) → 執(zhí)行初始化方法(本文重點) → Bean實例可用。

一、方式1:@PostConstruct注解修飾初始化方法

1.1 核心說明

@PostConstruct是JSR-250規(guī)范(Java EE標準)中定義的注解,并非Spring框架專屬,因此具有良好的通用性(可跨框架使用)。該注解僅需修飾在Bean的非靜態(tài)方法上(無參數、無返回值),當Spring容器完成Bean實例創(chuàng)建和依賴注入后,會自動調用該方法執(zhí)行初始化邏輯。

依賴要求:JDK9及以上版本中,javax.annotation-api包已被移除,需手動引入依賴(Maven示例如下);JDK8及以下版本可直接使用。

<dependency>
    <groupId>jakarta.annotation</groupId>
    <artifactId>jakarta.annotation-api</artifactId>
    <version>2.1.1</version>
</dependency>

1.2 完整代碼示例

示例包含4個核心類:依賴Bean(UserDao)、目標Bean(UserService,含@PostConstruct初始化方法)、Spring配置類(注冊Bean)、測試類(啟動容器驗證)。

// 1. 依賴Bean:UserDao(模擬數據訪問層,僅作注入示例)
public class UserDao {
    // 模擬UserDao的基礎功能
    public void initDao() {
        System.out.println("UserDao實例已創(chuàng)建");
    }
}

// 2. 目標Bean:UserService(核心業(yè)務類,含@PostConstruct初始化方法)
import javax.annotation.PostConstruct;

public class UserService {
    // 依賴注入UserDao(通過構造器注入,Spring會自動匹配)
    private final UserDao userDao;

    // 構造器:Spring容器會通過該構造器注入UserDao實例
    public UserService(UserDao userDao) {
        this.userDao = userDao;
        System.out.println("UserService構造方法執(zhí)行:已注入UserDao");
        // 注意:此處僅完成屬性注入,Bean尚未初始化,不建議執(zhí)行業(yè)務邏輯
    }

    // @PostConstruct修飾的初始化方法:Spring自動調用
    @PostConstruct
    public void initUserService() {
        System.out.println("@PostConstruct初始化方法執(zhí)行:");
        System.out.println("  - 加載用戶模塊配置文件");
        System.out.println("  - 初始化用戶緩存(如Redis用戶信息預熱)");
        System.out.println("  - 校驗用戶服務依賴資源(如數據庫連接)");
        // 實際開發(fā)中可在此處編寫核心初始化邏輯
    }

    // 模擬業(yè)務方法(驗證Bean可用)
    public void getUserInfo() {
        System.out.println("執(zhí)行用戶查詢業(yè)務:依賴UserDao完成數據獲取");
    }
}

// 3. Spring配置類:SpringConfig(注解式配置,替代XML)
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration // 標識該類為Spring配置類
public class SpringConfig {
    // 注冊UserDao Bean:Spring容器會管理該實例
    @Bean
    public UserDao userDao() {
        UserDao userDao = new UserDao();
        userDao.initDao(); // 可選:Dao層自身的簡單初始化
        return userDao;
    }

    // 注冊UserService Bean:注入UserDao依賴
    @Bean
    public UserService userService(UserDao userDao) {
        // Spring會自動將上面注冊的UserDao實例傳入構造器
        return new UserService(userDao);
    }
}

// 4. 測試類:BeanInitTest(啟動Spring容器,驗證初始化流程)
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class BeanInitTest {
    public static void main(String[] args) {
        // 1. 啟動Spring容器(加載注解配置)
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
        System.out.println("=== Spring容器啟動完成 ===");
        
        // 2. 獲取UserService Bean,驗證其可用
        UserService userService = context.getBean(UserService.class);
        userService.getUserInfo();
        
        // 3. 關閉容器(釋放資源)
        context.close();
    }
}

1.3 運行結果與解讀

UserDao實例已創(chuàng)建
UserService構造方法執(zhí)行:已注入UserDao
@PostConstruct初始化方法執(zhí)行:
  - 加載用戶模塊配置文件
  - 初始化用戶緩存(如Redis用戶信息預熱)
  - 校驗用戶服務依賴資源(如數據庫連接)
=== Spring容器啟動完成 ===
執(zhí)行用戶查詢業(yè)務:依賴UserDao完成數據獲取

解讀:從結果可見,執(zhí)行順序為「UserDao實例創(chuàng)建 → UserService構造方法(注入依賴) → @PostConstruct初始化方法 → Bean可用」,完全符合Spring Bean的初始化觸發(fā)時機。

二、方式2:實現InitializingBean接口(Spring原生方式)

2.1 核心說明

InitializingBean是Spring框架提供的原生接口,僅包含一個抽象方法:void afterPropertiesSet() throws Exception。當Bean實現該接口后,Spring容器在完成Bean實例創(chuàng)建和屬性注入后,會自動調用afterPropertiesSet()方法執(zhí)行初始化邏輯。

特點:與Spring框架強耦合(Bean直接依賴Spring API),但執(zhí)行時機精準,無需額外配置,適合需要深度對接Spring生命周期的場景。

2.2 完整代碼示例

基于方式1的基礎代碼修改,僅需調整UserService類(實現InitializingBean接口),其他類(UserDao、SpringConfig、測試類)保持不變。

// 目標Bean:UserService(實現InitializingBean接口)
import org.springframework.beans.factory.InitializingBean;

public class UserService implements InitializingBean {
    private final UserDao userDao;

    // 構造器注入UserDao
    public UserService(UserDao userDao) {
        this.userDao = userDao;
        System.out.println("UserService構造方法執(zhí)行:已注入UserDao");
    }

    // 重寫InitializingBean的afterPropertiesSet()方法:Spring自動調用
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("InitializingBean初始化方法(afterPropertiesSet)執(zhí)行:");
        System.out.println("  - 初始化用戶服務核心組件");
        System.out.println("  - 校驗UserDao依賴是否正??捎?);
        System.out.println("  - 加載用戶權限配置");
    }

    // 模擬業(yè)務方法
    public void getUserInfo() {
        System.out.println("執(zhí)行用戶查詢業(yè)務:依賴UserDao完成數據獲取");
    }
}

2.3 運行結果與解讀

UserDao實例已創(chuàng)建
UserService構造方法執(zhí)行:已注入UserDao
InitializingBean初始化方法(afterPropertiesSet)執(zhí)行:
  - 初始化用戶服務核心組件
  - 校驗UserDao依賴是否正??捎?
  - 加載用戶權限配置
=== Spring容器啟動完成 ===
執(zhí)行用戶查詢業(yè)務:依賴UserDao完成數據獲取

解讀:無需額外注解或配置,僅通過實現接口即可完成初始化邏輯的自動執(zhí)行,適合Spring專屬項目的開發(fā)場景。但需注意:若后續(xù)更換框架,該Bean需修改代碼(解耦成本高)。

三、方式3:通過init-method配置自定義初始化方法

3.1 核心說明

init-method是Spring提供的“配置式”初始化方式,支持兩種配置形式:① 注解配置(@Bean注解的initMethod屬性);② XML配置(傳統(tǒng)Spring項目常用)。該方式允許開發(fā)者自定義初始化方法名(無參數、無返回值),通過配置指定后,Spring容器會在Bean依賴注入完成后調用該方法。

特點:完全解耦(不依賴任何注解或接口),靈活性最高,適合傳統(tǒng)項目、舊代碼兼容或需要自定義方法名的場景。

3.2 代碼示例1:注解配置(@Bean(initMethod = “方法名”))

核心修改:UserService類中定義自定義初始化方法,SpringConfig類中通過@Bean指定initMethod屬性。

// 1. 目標Bean:UserService(含自定義初始化方法)
public class UserService {
    private final UserDao userDao;

    // 構造器注入UserDao
    public UserService(UserDao userDao) {
        this.userDao = userDao;
        System.out.println("UserService構造方法執(zhí)行:已注入UserDao");
    }

    // 自定義初始化方法(方法名可任意,如init、customInit等)
    public void userServiceInit() {
        System.out.println("init-method(注解配置)初始化方法執(zhí)行:");
        System.out.println("  - 初始化用戶模塊日志組件");
        System.out.println("  - 加載用戶業(yè)務規(guī)則配置");
        System.out.println("  - 初始化用戶數據統(tǒng)計緩存");
    }

    // 模擬業(yè)務方法
    public void getUserInfo() {
        System.out.println("執(zhí)行用戶查詢業(yè)務:依賴UserDao完成數據獲取");
    }
}

// 2. Spring配置類:通過@Bean指定initMethod
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class SpringConfig {
    @Bean
    public UserDao userDao() {
        UserDao userDao = new UserDao();
        userDao.initDao();
        return userDao;
    }

    // 關鍵:通過initMethod屬性指定自定義初始化方法名(userServiceInit)
    @Bean(initMethod = "userServiceInit")
    public UserService userService(UserDao userDao) {
        return new UserService(userDao);
    }
}

運行結果(其他類不變):

UserDao實例已創(chuàng)建
UserService構造方法執(zhí)行:已注入UserDao
init-method(注解配置)初始化方法執(zhí)行:
  - 初始化用戶模塊日志組件
  - 加載用戶業(yè)務規(guī)則配置
  - 初始化用戶數據統(tǒng)計緩存
=== Spring容器啟動完成 ===
執(zhí)行用戶查詢業(yè)務:依賴UserDao完成數據獲取

3.3 代碼示例2:XML配置(傳統(tǒng)Spring項目)

對于使用XML配置的傳統(tǒng)Spring項目(如SSM框架),可通過標簽的init-method屬性指定初始化方法。核心修改:移除注解配置,編寫XML配置文件。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans 
                           http://www.springframework.org/schema/beans/spring-beans.xsd">

    
    <bean id="userDao" class="com.example.UserDao"></bean>

    
    <bean id="userService" class="com.example.UserService" init-method="userServiceInit">
        
        <constructor-arg ref="userDao"/>
    </bean>
</beans>
// 2. 測試類(加載XML配置啟動容器)
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class BeanInitXmlTest {
    public static void main(String[] args) {
        // 加載XML配置文件啟動Spring容器
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        System.out.println("=== Spring容器啟動完成 ===");
        
        // 獲取Bean并驗證
        UserService userService = context.getBean(UserService.class);
        userService.getUserInfo();
        
        // 關閉容器
        context.close();
    }
}

運行結果與注解配置一致,適合不使用注解的傳統(tǒng)項目場景。

四、關鍵補充:三種方式的執(zhí)行順序驗證

若同一Bean同時使用三種初始化方式,執(zhí)行順序如何?我們通過代碼驗證(核心修改UserService類,同時包含三種方式):

import org.springframework.beans.factory.InitializingBean;
import javax.annotation.PostConstruct;

public class UserService implements InitializingBean {
    private final UserDao userDao;

    public UserService(UserDao userDao) {
        this.userDao = userDao;
        System.out.println("1. UserService構造方法執(zhí)行");
    }

    // 方式1:@PostConstruct
    @PostConstruct
    public void initByPostConstruct() {
        System.out.println("2. @PostConstruct初始化方法執(zhí)行");
    }

    // 方式2:InitializingBean
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("3. InitializingBean(afterPropertiesSet)執(zhí)行");
    }

    // 方式3:init-method自定義方法
    public void userServiceInit() {
        System.out.println("4. init-method初始化方法執(zhí)行");
    }
}

SpringConfig配置:@Bean(initMethod = "userServiceInit"),運行結果:

UserDao實例已創(chuàng)建
1. UserService構造方法執(zhí)行
2. @PostConstruct初始化方法執(zhí)行
3. InitializingBean(afterPropertiesSet)執(zhí)行
4. init-method初始化方法執(zhí)行
=== Spring容器啟動完成 ===

結論:執(zhí)行順序固定為 → @PostConstruct(1)→ InitializingBean(2)→ init-method(3)。

五、三種方式對比表(實戰(zhàn)選型依據)

初始化方式執(zhí)行順序核心優(yōu)勢潛在缺點適用場景
@PostConstruct注解1(最先)1. 基于JSR-250規(guī)范,跨框架通用;2. 低耦合(不依賴Spring);3. 使用簡單(僅需注解)JDK9+需手動引入jakarta.annotation-api依賴絕大多數注解式開發(fā)場景(如Spring Boot項目),追求框架解耦
實現InitializingBean接口2(中間)1. Spring原生支持,執(zhí)行時機精準;2. 無需額外配置(僅實現接口)1. 與Spring強耦合;2. 代碼侵入性高(Bean需實現特定接口)需要深度對接Spring生命周期,或Spring專屬項目
init-method配置(注解/XML)3(最后)1. 完全解耦(無注解/接口依賴);2. 靈活性最高(自定義方法名);3. 支持XML/注解雙配置1. 注解配置需手動指定方法名(易寫錯);2. XML配置較繁瑣1. 傳統(tǒng)XML配置項目;2. 舊代碼兼容;3. 需自定義初始化方法名的場景

六、實戰(zhàn)注意事項(避坑指南)

  • 初始化方法需滿足:無參數、無返回值,且不能是靜態(tài)方法(static修飾會導致Spring無法調用)。
  • @PostConstruct依賴問題:JDK9及以上版本需引入jakarta.annotation-api依賴,否則會報“找不到@PostConstruct注解”錯誤。
  • 避免在構造器中執(zhí)行初始化邏輯:構造器僅負責屬性注入,此時Bean尚未完全創(chuàng)建,若執(zhí)行業(yè)務邏輯可能導致依賴未就緒(如NullPointerException)。
  • init-method方法名匹配:注解配置(@Bean(initMethod))或XML配置時,方法名需與Bean中的自定義方法名完全一致(大小寫敏感),否則Spring無法識別。
  • 多初始化方式共存:實際開發(fā)中不建議同一Bean同時使用多種方式(易造成邏輯混亂),優(yōu)先選擇一種符合項目技術棧的方式即可。

七、總結

本文詳細講解了Spring Bean初始化的三種核心方式,結合完整代碼示例、執(zhí)行順序驗證、場景對比及避坑指南,可總結為:

  1. 優(yōu)先選擇:@PostConstruct注解(通用性強、低耦合,適合Spring Boot等注解式項目);
  2. 特殊場景:實現InitializingBean接口(Spring專屬項目,需精準對接生命周期);
  3. 兼容場景:init-method配置(傳統(tǒng)XML項目、舊代碼兼容,完全解耦)。

掌握這三種方式的核心邏輯和適用場景,能幫助你在實際開發(fā)中靈活處理Bean的初始化需求,避免踩坑。若需進一步學習Bean的銷毀方式(如@PreDestroy、DisposableBean接口、destroy-method配置),可留言補充~

以上就是Spring Bean初始化的三種常用方式(易懂版)的詳細內容,更多關于Spring Bean初始化的資料請關注腳本之家其它相關文章!

相關文章

  • JAVA操作MongoDB數據庫實例教程

    JAVA操作MongoDB數據庫實例教程

    MongoDB是一個文檔型數據庫,是NOSQL家族中最重要的成員之一,下面這篇文章主要給大家介紹了關于JAVA操作MongoDB數據庫的相關資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2023-05-05
  • UniApp?+?SpringBoot?實現支付寶支付和退款功能

    UniApp?+?SpringBoot?實現支付寶支付和退款功能

    這篇文章主要介紹了UniApp?+?SpringBoot?實現支付寶支付和退款功能,基本的?SpringBoot?的腳手架,可以去IDEA?自帶的快速生成腳手架插件,本文通過實例代碼給大家介紹的非常詳細,需要的朋友參考下吧
    2022-06-06
  • Java計算幾何圖形面積的實例代碼

    Java計算幾何圖形面積的實例代碼

    這篇文章主要介紹了Java計算幾何圖形面積的實例代碼,需要的朋友可以參考下
    2014-03-03
  • 解析Java按值傳遞還是按引用傳遞

    解析Java按值傳遞還是按引用傳遞

    這篇文章主要介紹了解析Java按值傳遞還是按引用傳遞,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-01-01
  • 2020最新eclipse安裝過程及細節(jié)

    2020最新eclipse安裝過程及細節(jié)

    這篇文章主要介紹了2020最新eclipse安裝過程及細節(jié),本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-08-08
  • SpringBoot+Flying Saucer+Thymeleaf實現PDF生成的完整指南

    SpringBoot+Flying Saucer+Thymeleaf實現PDF生成的完整指南

    在實際開發(fā)中,PDF生成是常見需求,本文將詳細講解如何基于 Spring Boot + Flying Saucer + Thymeleaf 實現 PDF 生成,文中的示例代碼講解詳細,感興趣的小伙伴可以了解下
    2026-01-01
  • Java.lang.OutOfMemoryError: GC overhead limit exceeded錯誤的解決

    Java.lang.OutOfMemoryError: GC overhead limit

    本文主要介紹了Java.lang.OutOfMemoryError: GC overhead limit exceeded錯誤的解決,錯誤是由于堆空間不足導致GC頻繁運行,從而引起的,下面就來介紹一下解決方法
    2025-03-03
  • Spring中Bean的生命周期使用解析

    Spring中Bean的生命周期使用解析

    這篇文章主要介紹了Spring中Bean的生命周期使用解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-09-09
  • mybatis中#{}和${}的區(qū)別詳解

    mybatis中#{}和${}的區(qū)別詳解

    本文主要介紹了mybatis中#{}和${}的區(qū)別詳解,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • 解決feign之間文件上傳報錯:Error converting request body的問題

    解決feign之間文件上傳報錯:Error converting request body

    這篇文章主要介紹了解決feign之間文件上傳報錯:Error converting request body的問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2025-05-05

最新評論

安溪县| 句容市| 铁岭市| 云龙县| 西城区| 虎林市| 长汀县| 都兰县| 江油市| 承德县| 黑龙江省| 昌宁县| 喀什市| 额济纳旗| 中宁县| 仁化县| 卫辉市| 巫溪县| 临西县| 阿图什市| 昌宁县| 兴安县| 双江| 杭锦后旗| 元氏县| 克东县| 江油市| 林西县| 桦川县| 车险| 阳西县| 玉树县| 尉犁县| 孝义市| 沙田区| 彰化市| 虹口区| 化隆| 信宜市| 南投县| 天镇县|