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

SpringBoot靜態(tài)類調(diào)用Bean的兩種方案(新手版)

 更新時(shí)間:2025年12月05日 09:48:47   作者:Dolphin_Home  
這篇文章主要介紹了兩種解決Spring Boot中靜態(tài)類調(diào)用Bean問題的方法:方案一使用SpringContextHolder(中間人模式),方案二使用@PostConstruct注解(入住模式),根據(jù)具體需求選擇合適的方案,需要的朋友可以參考下

一、開篇痛點(diǎn):靜態(tài)類調(diào)用Bean,小白必遇的“攔路虎”

剛接觸SpringBoot的同學(xué),大概率會(huì)碰到這個(gè)問題:
寫了個(gè)靜態(tài)工具類(比如 MyStaticUtils),想在靜態(tài)方法里調(diào)用Spring管理的Bean(比如 UserService),用 @Autowired 直接注入?yún)s報(bào) NullPointerException!

比如想實(shí)現(xiàn)“根據(jù)用戶ID查用戶名”的靜態(tài)方法,直接這么寫必錯(cuò):

// 錯(cuò)誤示范
public class MyStaticUtils {
    @Autowired
    private static UserService userService; // 注入失敗,永遠(yuǎn)是null

    public static String getUserNameById(Long userId) {
        return userService.getUserName(userId); // 運(yùn)行時(shí)空指針
    }
}

核心原因還是之前說的:靜態(tài)類加載時(shí)機(jī)早于Spring Bean初始化,@Autowired 是給Spring實(shí)例注入Bean的,管不到靜態(tài)變量。

今天就給大家講兩種解決方案,重點(diǎn)對(duì)比侵入性差異,幫小白按需選擇!

二、兩方案侵入性對(duì)比(一眼看懂區(qū)別)

先上核心對(duì)比表,小白不用記復(fù)雜邏輯,看表格就知道差異:

對(duì)比維度方案一:SpringContextHolder(中間人模式)方案二:@PostConstruct注解(入住模式)
核心思路用中間類持有Spring上下文,靜態(tài)類按需獲取Bean讓靜態(tài)類被Spring管理,初始化后給靜態(tài)變量賦值
代碼侵入性低(靜態(tài)類無需加Spring注解,保持純靜態(tài)特性)高(靜態(tài)類需加@Component,依賴Spring注解)
實(shí)現(xiàn)復(fù)雜度中等(需新增1個(gè)中間類)簡(jiǎn)單(無需新增類,僅改靜態(tài)工具類)
靜態(tài)類獨(dú)立性強(qiáng)(可脫離Spring單獨(dú)使用)弱(必須被Spring掃描管理,否則失效)
適用場(chǎng)景不想修改靜態(tài)類結(jié)構(gòu)、侵入性要求低的場(chǎng)景靜態(tài)類可被Spring管理、邏輯簡(jiǎn)單的場(chǎng)景

簡(jiǎn)單說:方案一是“找中間人拿工具”,方案二是“讓靜態(tài)類住進(jìn)Spring的房子里直接拿工具”。

三、方案一:SpringContextHolder(低侵入,通用方案)

1. 核心邏輯

通過一個(gè)“中間人”(SpringContextHolder)持有Spring的上下文(ApplicationContext),靜態(tài)類需要Bean時(shí),直接問“中間人”要,不用自己依賴Spring。

2. 快速實(shí)現(xiàn)(簡(jiǎn)要回顧,重點(diǎn)看對(duì)比)

// 1. 中間人:SpringContextHolder(直接復(fù)制可用)
@Component
public class SpringContextHolder implements ApplicationContextAware {
    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext context) {
        SpringContextHolder.applicationContext = context;
    }

    // 靜態(tài)方法:獲取Bean
    public static <T> T getBean(Class<T> clazz) {
        return applicationContext.getBean(clazz);
    }
}

// 2. 靜態(tài)工具類調(diào)用(無需加任何Spring注解)
public class MyStaticUtils {
    public static String getUserNameById(Long userId) {
        // 關(guān)鍵:通過中間人獲取Bean
        UserService userService = SpringContextHolder.getBean(UserService.class);
        return userService.getUserName(userId);
    }
}

3. 核心優(yōu)勢(shì)

靜態(tài)類還是“純靜態(tài)”,不用加 @Component,就算脫離Spring環(huán)境也能單獨(dú)使用,侵入性極低。

四、方案二:@PostConstruct注解(高侵入,簡(jiǎn)單方案)

這就是你找到的CSDN方案,核心是“讓靜態(tài)類被Spring管理”,通過注解在Bean初始化后給靜態(tài)變量賦值,巧妙但侵入性強(qiáng)。

1. 核心原理(小白通俗理解)

  • 給靜態(tài)工具類加 @Component,讓它變成Spring管理的Bean(住進(jìn)Spring的“房子”);
  • @Autowired 先給實(shí)例變量注入Bean(Spring能管理實(shí)例變量);
  • @PostConstruct 注解一個(gè)初始化方法,在Spring初始化這個(gè)工具類后,把實(shí)例變量的值賦給靜態(tài)變量;
  • 靜態(tài)方法直接用靜態(tài)變量調(diào)用Bean,就不會(huì)空指針了。

2. 分步實(shí)現(xiàn)(還是用“查用戶名”案例)

步驟1:創(chuàng)建Spring管理的Bean(UserService)

和之前一致,模擬查詢邏輯:

@Service
public class UserService {
    // 模擬根據(jù)ID查用戶名
    public String getUserName(Long userId) {
        return userId == 1 ? "張三" : "未知用戶";
    }
}

步驟2:改造靜態(tài)工具類(核心改造)

給工具類加 @Component,配合 @Autowired@PostConstruct

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;

// 關(guān)鍵1:加@Component,讓Spring管理這個(gè)工具類
@Component
public class MyStaticUtils {
    // 關(guān)鍵2:先注入實(shí)例變量(Spring能識(shí)別@Autowired)
    @Autowired
    private UserService userService;

    // 關(guān)鍵3:靜態(tài)變量(供靜態(tài)方法使用)
    private static MyStaticUtils staticUtils;

    // 關(guān)鍵4:@PostConstruct:Spring初始化當(dāng)前Bean后執(zhí)行(初始化順序:構(gòu)造方法→@Autowired→@PostConstruct)
    @PostConstruct
    public void init() {
        // 把當(dāng)前實(shí)例賦值給靜態(tài)變量
        staticUtils = this;
    }

    // 靜態(tài)方法:通過靜態(tài)變量調(diào)用Bean的方法
    public static String getUserNameById(Long userId) {
        // 核心:staticUtils持有實(shí)例,實(shí)例持有注入的userService
        return staticUtils.userService.getUserName(userId);
    }
}

步驟3:測(cè)試驗(yàn)證

寫個(gè)Controller調(diào)用:

@RestController
public class TestController {
    @GetMapping("/user/{userId}")
    public String getUserName(@PathVariable Long userId) {
        return MyStaticUtils.getUserNameById(userId); // 調(diào)用靜態(tài)方法
    }
}

啟動(dòng)項(xiàng)目訪問 http://localhost:8080/user/1,返回“張三”—— 成功!

3. 原理拆解(小白必懂)

用“房子”比喻再講一遍:

  1. @ComponentMyStaticUtils 住進(jìn)了Spring的“房子”,成為Spring管理的Bean;
  2. Spring初始化時(shí),先執(zhí)行 @Autowired,給實(shí)例變量 userService 注入Bean(相當(dāng)于給房子里放了工具);
  3. 再執(zhí)行 @PostConstruct 標(biāo)注的 init() 方法,把當(dāng)前實(shí)例(this)賦給靜態(tài)變量 staticUtils(相當(dāng)于給房子配了把“靜態(tài)鑰匙”);
  4. 靜態(tài)方法通過 staticUtils 這把鑰匙,就能拿到房子里的 userService 工具了。

五、方案二關(guān)鍵注意事項(xiàng)(小白避坑)

  1. 必須加 @Component:否則Spring不會(huì)管理這個(gè)工具類,@Autowired@PostConstruct 都無效,靜態(tài)變量還是null;
  2. 實(shí)例變量+靜態(tài)變量配合:不能直接給靜態(tài)變量加 @Autowired(Spring不支持),必須先注入實(shí)例變量,再通過 @PostConstruct 賦值給靜態(tài)變量;
  3. @PostConstruct 執(zhí)行時(shí)機(jī):在構(gòu)造方法之后、Bean初始化完成之前執(zhí)行,只會(huì)執(zhí)行一次,確保靜態(tài)變量只賦值一次;
  4. 不能在靜態(tài)代碼塊中調(diào)用:靜態(tài)代碼塊加載時(shí)機(jī)早于 @PostConstruct,此時(shí) staticUtils 還沒賦值,調(diào)用會(huì)空指針。

六、適用場(chǎng)景總結(jié)(小白怎么選?)

場(chǎng)景描述推薦方案理由
靜態(tài)工具類不想被Spring管理、需保持獨(dú)立性方案一:SpringContextHolder侵入性低,工具類可脫離Spring使用
靜態(tài)工具類僅在Spring環(huán)境中使用、邏輯簡(jiǎn)單方案二:@PostConstruct無需新增中間類,代碼量少,實(shí)現(xiàn)簡(jiǎn)單
項(xiàng)目中靜態(tài)工具類較多、需統(tǒng)一管理方案一:SpringContextHolder中間類可復(fù)用,維護(hù)成本低
不想新增額外類、快速實(shí)現(xiàn)需求方案二:@PostConstruct直接改造工具類,幾分鐘就能搞定

七、最終建議(小白牢記)

  1. 如果你是“純小白”,只是想快速實(shí)現(xiàn)需求,且靜態(tài)工具類只在Spring項(xiàng)目中用,選方案二(@PostConstruct),代碼簡(jiǎn)單不用記中間類;
  2. 如果你想讓代碼更規(guī)范、侵入性更低,或者靜態(tài)工具類可能脫離Spring使用,選方案一(SpringContextHolder),通用性更強(qiáng);
  3. 兩種方案的核心都是“解決靜態(tài)類和Spring Bean加載時(shí)機(jī)不匹配的問題”,只是實(shí)現(xiàn)思路不同,沒有絕對(duì)優(yōu)劣,按需選擇即可。

其實(shí)這兩種方案本質(zhì)是“取舍”:方案二用“侵入性”換“簡(jiǎn)單性”,方案一用“多一個(gè)中間類”換“低侵入性”。學(xué)會(huì)這兩種,以后遇到靜態(tài)類調(diào)用Bean的問題,再也不用一頭霧水啦!

以上就是SpringBoot靜態(tài)類調(diào)用Bean的兩種方案(新手版)的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot靜態(tài)類調(diào)用Bean的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 將本地SpringBoot項(xiàng)目發(fā)布到云服務(wù)器的方法

    將本地SpringBoot項(xiàng)目發(fā)布到云服務(wù)器的方法

    這篇文章主要介紹了如何將本地SpringBoot項(xiàng)目發(fā)布到云服務(wù)器,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-12-12
  • Future與FutureTask接口實(shí)現(xiàn)示例詳解

    Future與FutureTask接口實(shí)現(xiàn)示例詳解

    這篇文章主要為大家介紹了Future與FutureTask接口實(shí)現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-10-10
  • Java中的權(quán)重算法(如Dubbo的負(fù)載均衡權(quán)重)詳解

    Java中的權(quán)重算法(如Dubbo的負(fù)載均衡權(quán)重)詳解

    這篇文章主要介紹了Java中的權(quán)重算法(如Dubbo的負(fù)載均衡權(quán)重)詳解,負(fù)載均衡,其含義就是指將負(fù)載進(jìn)行平衡、分?jǐn)偟蕉鄠€(gè)操作單元上進(jìn)行運(yùn)行,例如FTP服務(wù)器、Web服務(wù)器、企業(yè)核心應(yīng)用服務(wù)器和其它主要任務(wù)服務(wù)器等,從而協(xié)同完成工作任務(wù),需要的朋友可以參考下
    2023-08-08
  • 詳解Java并發(fā)工具類之CountDownLatch和CyclicBarrier

    詳解Java并發(fā)工具類之CountDownLatch和CyclicBarrier

    在JDK的并發(fā)包中,有幾個(gè)非常有用的并發(fā)工具類,它們分別是:CountDownLatch、CyclicBarrier、Semaphore和Exchanger,本文主要來講講其中CountDownLatch和CyclicBarrier的使用,感興趣的可以了解一下
    2023-06-06
  • SpringBoot、Java 使用 Jsoup 解析 HTML 頁(yè)面的詳細(xì)步驟

    SpringBoot、Java 使用 Jsoup 解析 HTML 頁(yè)面

    這篇文章主要介紹了SpringBoot、Java 使用 Jsoup 解析 HTML 頁(yè)面的詳細(xì)步驟,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-08-08
  • spring基礎(chǔ)概念A(yù)OP與動(dòng)態(tài)代理理解

    spring基礎(chǔ)概念A(yù)OP與動(dòng)態(tài)代理理解

    這篇文章主要為大家詳細(xì)介紹了spring基礎(chǔ)概念A(yù)OP與動(dòng)態(tài)代理,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-10-10
  • 詳解java連接mysql數(shù)據(jù)庫(kù)的五種方式

    詳解java連接mysql數(shù)據(jù)庫(kù)的五種方式

    這篇文章主要介紹了詳解java連接mysql數(shù)據(jù)庫(kù)的五種方式,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • Java模仿微信實(shí)現(xiàn)零錢通簡(jiǎn)易功能(兩種版本)

    Java模仿微信實(shí)現(xiàn)零錢通簡(jiǎn)易功能(兩種版本)

    本文主要介紹了使用Java開發(fā)零錢通項(xiàng)目, 模仿微信實(shí)現(xiàn)簡(jiǎn)易功能,可以完成收益入賬,消費(fèi),查看明細(xì),退出系統(tǒng)等功能。文中一共介紹了兩種實(shí)現(xiàn)方法,快來學(xué)習(xí)吧
    2021-12-12
  • Java常用 Date 時(shí)間格式化、Calender日歷、正則表達(dá)式的用法小結(jié)

    Java常用 Date 時(shí)間格式化、Calender日歷、正則表達(dá)式的用法小結(jié)

    SimpleDateFormat?是Java中用于格式化和解析日期的類,它允許你將日期對(duì)象轉(zhuǎn)換為特定格式的字符串,或者將特定格式的字符串轉(zhuǎn)換為日期對(duì)象,這篇文章主要介紹了Java常用 Date 時(shí)間格式化、Calender日歷、正則表達(dá)式的用法,需要的朋友可以參考下
    2024-12-12
  • Java編程之雙重循環(huán)打印圖形

    Java編程之雙重循環(huán)打印圖形

    這篇文章主要介紹了Java編程之雙重循環(huán)打印圖形,屬于Java編程基礎(chǔ)練習(xí)部分,具有一定參考價(jià)值,需要的朋友可以了解下。
    2017-11-11

最新評(píng)論

中宁县| 长春市| 尉氏县| 宁夏| 虹口区| 仁化县| 都昌县| 平邑县| 繁峙县| 台北县| 志丹县| 乐业县| 仙游县| 隆回县| 商水县| 蚌埠市| 长泰县| 临漳县| 德保县| 大石桥市| 民丰县| 彭阳县| 利津县| 五家渠市| 黎平县| 漳浦县| 荔波县| 唐海县| 夏邑县| 库尔勒市| 方城县| 赤峰市| 犍为县| 五寨县| 分宜县| 冷水江市| 秦皇岛市| 陇川县| 突泉县| 武宁县| 丁青县|