SpringBoot 中給 @Autowired 搭配 @Lazy的使用
在 SpringBoot 中給 @Autowired 搭配 @Lazy 使用是合法且常見的做法,但并非完全沒有需要注意的問題,核心是要理解 @Lazy 的作用機(jī)制以及它可能帶來的影響。
一、先理解核心概念
@Lazy 的核心作用是:將 Bean 的初始化時(shí)機(jī)從 Spring 容器啟動(dòng)時(shí)(餓漢式)推遲到該 Bean 第一次被使用時(shí)(懶漢式)。給 @Autowired 加 @Lazy 有兩種常見場景:
- 直接標(biāo)注在
@Autowired字段 / 方法上:延遲注入的這個(gè) Bean 本身的初始化 - 標(biāo)注在被注入的 Bean 類上:全局延遲該 Bean 的初始化
二、可能遇到的問題及注意事項(xiàng)
1. 初始化異常延遲暴露
這是最常見的問題:
- 正常情況:非懶加載的 Bean 在容器啟動(dòng)時(shí)初始化,若存在依賴缺失、配置錯(cuò)誤等問題,會(huì)直接報(bào)錯(cuò),能快速發(fā)現(xiàn)問題。
- 加 @Lazy 后:Bean 初始化推遲到第一次使用時(shí),容器啟動(dòng)時(shí)不會(huì)報(bào)錯(cuò),但在運(yùn)行時(shí)第一次調(diào)用該 Bean 時(shí)才拋出異常(比如
NullPointerException、NoSuchBeanDefinitionException),可能導(dǎo)致線上故障。
示例:
@Service
public class OrderService {
// 延遲注入 UserService
@Lazy
@Autowired
private UserService userService;
public void processOrder() {
// 第一次調(diào)用時(shí)才初始化 userService,若 userService 有初始化異常,此時(shí)才會(huì)報(bào)錯(cuò)
userService.validateUser();
}
}2. 循環(huán)依賴場景的影響
Spring 默認(rèn)能解決單例 Bean 的循環(huán)依賴,但 @Lazy 會(huì)改變循環(huán)依賴的處理邏輯:
- 不加
@Lazy:Spring 通過三級(jí)緩存提前暴露 Bean 的早期引用解決循環(huán)依賴。 - 加
@Lazy:會(huì)直接返回一個(gè)代理對象(而非早期引用),雖然能解決更復(fù)雜的循環(huán)依賴,但如果對代理對象的類型敏感(比如強(qiáng)轉(zhuǎn)),可能拋出ClassCastException。
反例(可能報(bào)錯(cuò)):
@Service
public class AService {
@Lazy
@Autowired
private BService bService;
public void test() {
// 錯(cuò)誤:bService 是代理對象,強(qiáng)轉(zhuǎn)可能失敗
BServiceImpl b = (BServiceImpl) bService;
}
}
@Service
public class BService {
@Autowired
private AService aService;
}3. 性能與資源問題
- 首次調(diào)用耗時(shí)增加:第一次使用 Bean 時(shí)需要完成初始化(實(shí)例化、依賴注入、初始化方法執(zhí)行),可能導(dǎo)致首次請求響應(yīng)變慢(比如接口首次調(diào)用超時(shí))。
- 資源占用延遲:若 Bean 初始化需要占用大量資源(如連接數(shù)據(jù)庫、加載緩存),延遲初始化會(huì)把資源占用的時(shí)機(jī)從啟動(dòng)時(shí)轉(zhuǎn)移到運(yùn)行時(shí),可能影響服務(wù)運(yùn)行時(shí)的資源分配。
4. 與作用域的兼容問題
@Lazy 對原型(Prototype)Bean 無效:原型 Bean 本身就是每次獲取時(shí)新建,不存在 “延遲初始化” 的概念;若給請求作用域(Request)、會(huì)話作用域(Session)的 Bean 加 @Lazy,需要確保在對應(yīng)的作用域上下文(如 Web 請求中)使用,否則可能拋出 ScopeNotActiveException。
三、正確使用 @Lazy 的場景(避坑建議)
- 解決循環(huán)依賴:這是
@Lazy最核心的合法用途,優(yōu)先用它解決循環(huán)依賴,而非重構(gòu)代碼(短期方案)。 - 優(yōu)化啟動(dòng)速度:對初始化耗時(shí)的 Bean(如大數(shù)據(jù)量緩存加載),延遲初始化能加快 Spring 容器啟動(dòng)速度。
- 按需加載 Bean:某些 Bean 僅在特定場景下使用(如定時(shí)任務(wù)、管理接口),延遲初始化可節(jié)省啟動(dòng)資源。
四、避坑最佳實(shí)踐
- 核心業(yè)務(wù) Bean 避免 @Lazy:核心流程的 Bean 建議餓漢式初始化,確保啟動(dòng)時(shí)暴露所有問題。
- 配合異常監(jiān)控:若必須用
@Lazy,在首次調(diào)用處增加異常捕獲和日志,便于定位問題。 - 測試覆蓋:對懶加載的 Bean,編寫專門的測試用例,主動(dòng)觸發(fā)初始化,避免線上首次調(diào)用報(bào)錯(cuò)。
- 替代方案優(yōu)先:能通過重構(gòu)代碼(如引入中間層、拆分服務(wù))解決循環(huán)依賴的,優(yōu)先重構(gòu),而非依賴
@Lazy。
到此這篇關(guān)于SpringBoot 中給 @Autowired 搭配 @Lazy的文章就介紹到這了,更多相關(guān)SpringBoot @Autowired 搭配 @Lazy內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- SpringBoot中@Autowired 失效及@Autowired 注入為null的解決
- SpringBoot中@Autowired注入service時(shí)出現(xiàn)循環(huán)依賴問題的解決方法
- SpringBoot注解篇之@Resource與@Autowired的使用區(qū)別
- SpringBoot中@Autowired生效方式詳解
- springboot?靜態(tài)方法中使用@Autowired注入方式
- SpringBoot使用@Autowired為多實(shí)現(xiàn)的接口注入依賴
- springBoot Junit測試用例出現(xiàn)@Autowired不生效的解決
- 解決SpringBoot 測試類無法自動(dòng)注入@Autowired的問題
- 詳解SpringBoot 多線程處理任務(wù) 無法@Autowired注入bean問題解決
相關(guān)文章
Java畢業(yè)設(shè)計(jì)實(shí)戰(zhàn)之仿小米電子產(chǎn)品售賣商城系統(tǒng)的實(shí)現(xiàn)
這是一個(gè)使用了java+SpringBoot+Vue+MySQL+Redis+ElementUI開發(fā)的仿小米商城系統(tǒng),是一個(gè)畢業(yè)設(shè)計(jì)的實(shí)戰(zhàn)練習(xí),具有小米商城該有的所有基礎(chǔ)功能,感興趣的朋友快來看看吧2022-01-01
Java實(shí)現(xiàn)從Word文檔中提取文本和圖像
在 Java 開發(fā)項(xiàng)目中,處理 Microsoft Word 文檔是常見場景,例如,內(nèi)容管理系統(tǒng)需要批量解析文檔文本用于搜索索引,數(shù)據(jù)遷移工具需分離圖像以便獨(dú)立存儲(chǔ),本文介紹如何借助 Spire.Doc for Java 庫實(shí)現(xiàn)這一功能,需要的朋友可以參考下2026-03-03
如何用Intellij idea2020打包jar的方法步驟
這篇文章主要介紹了如何用Intellij idea 2020打包jar的方法步驟,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-04-04
Mybatis Log控制臺(tái)如何輸出打印SQL語句
這篇文章主要介紹了Mybatis Log控制臺(tái)如何輸出打印SQL語句,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-07-07
Java實(shí)現(xiàn)將PDF轉(zhuǎn)為圖片格式的方法詳解
PDF文件和圖片文件,這是兩種完全不一樣的格式,可是有的時(shí)候這兩種格式卻是有相互轉(zhuǎn)換的需要,本文將介紹如何通過Java應(yīng)用程序快速高效地將PDF轉(zhuǎn)為圖片格式。一起來看看吧2023-03-03
java 中 阻塞隊(duì)列BlockingQueue詳解及實(shí)例
這篇文章主要介紹了java 中 阻塞隊(duì)列BlockingQueue詳解及實(shí)例的相關(guān)資料,需要的朋友可以參考下2017-03-03

