javascript
Spring的依赖注入陷阱
Spring框架中有三種注入變量:
- 基于二傳手的注射
- 基于構(gòu)造函數(shù)的注入
- 基于現(xiàn)場(chǎng)的注入
這些機(jī)制中的每一種都有優(yōu)點(diǎn)和缺點(diǎn),并且不僅只有一種正確的方法。 例如現(xiàn)場(chǎng)注入:
在生產(chǎn)代碼中使用它通常不是最好的主意,主要是因?yàn)樗刮覀兊腷ean無(wú)法在不啟動(dòng)Spring上下文或不使用反射hack的情況下進(jìn)行測(cè)試。 另一方面,它幾乎不需要其他代碼,并且可以在集成測(cè)試中使用-絕對(duì)不會(huì)獨(dú)立實(shí)例化。 在我看來(lái),這是基于現(xiàn)場(chǎng)注射的唯一情況。
現(xiàn)在,讓我們關(guān)注兩個(gè)主要變體。 在Spring文檔中,我們可以讀到
…將構(gòu)造函數(shù)參數(shù)用于強(qiáng)制性依賴項(xiàng)并將設(shè)置器用于可選的依賴項(xiàng)是一個(gè)很好的經(jīng)驗(yàn)法則。
同樣在參考Spring到3.1的文檔中 ,我們可以找到一個(gè)句子
Spring團(tuán)隊(duì)通常提倡setter注入,因?yàn)榇罅康臉?gòu)造函數(shù)參數(shù)可能變得笨拙,尤其是當(dāng)屬性是可選的時(shí)。
這種情況在文檔中已更改為第四版,其中指出:
Spring團(tuán)隊(duì)通常提倡構(gòu)造函數(shù)注入,因?yàn)樗谷藗兡軌驅(qū)?yīng)用程序組件實(shí)現(xiàn)為不可變對(duì)象,并確保所需的依賴項(xiàng)不為null。
尤其是在版本4.0之前的人們使用基于構(gòu)造函數(shù)的注入方式(其中有些“純粹主義者”(也可以在本文檔中找到))時(shí), 這非常酷:)請(qǐng)注意,在第四個(gè)框架發(fā)布之前,這種注入方式存在很大的問(wèn)題–方面要求使用默認(rèn)構(gòu)造函數(shù)。 現(xiàn)在仍然存在基于構(gòu)造函數(shù)的注入的“缺點(diǎn)”:它不允許循環(huán)依賴。 我特意在雙引號(hào)中添加了缺陷,因?yàn)閷?duì)我而言,這是該機(jī)制的巨大優(yōu)勢(shì):)文檔中還有另外一句話:
通常建議不要在bean之間使用循環(huán)引用。
但為什么? 如果我們的應(yīng)用程序中有循環(huán)引用,該怎么辦? 我不想寫關(guān)于應(yīng)用程序設(shè)計(jì)的文章,因?yàn)閹缀蹩偸强梢灾貥?gòu)我們的代碼并將有問(wèn)題的邏輯委托給第三個(gè)bean。 有兩個(gè)重大而不幸的“沉默”問(wèn)題。
第一個(gè)陷阱
調(diào)用ListableBeanFactory.getBeansOfType()方法時(shí),不能確定將返回哪些Bean。 讓我們看一下DefaultListableBeanFactory類的代碼:
if (isCurrentlyInCreation(bce.getBeanName())) {if (this.logger.isDebugEnabled()) {this.logger.debug("Ignoring match to currently created bean '"+ beanName + "': " + ex.getMessage());}// ...continue; }如您所見,如果您不使用DEBUG日志記錄級(jí)別,那么將有零個(gè)信息表明Spring在解析過(guò)程中跳過(guò)了特定的bean。 如果您想獲得所有事件處理程序,那就太麻煩了:)
第二個(gè)陷阱
第二個(gè)問(wèn)題涉及AOP。 如果要在bean上使用方面,請(qǐng)確保它不涉及循環(huán)引用-否則Spring將創(chuàng)建bean的兩個(gè)實(shí)例–一個(gè)沒(méi)有方面,另一個(gè)具有適當(dāng)方面。 當(dāng)然仍然沒(méi)有任何信息。 驚訝嗎
對(duì)我來(lái)說(shuō), 停止在我們的應(yīng)用程序中使用循環(huán)依賴就足夠了(特別是與此相關(guān)的行為可能更有趣)。
請(qǐng)勿使用循環(huán)依賴!
但是,我們?cè)撊绾螖[脫困境呢? 當(dāng)然,您可以使用基于構(gòu)造函數(shù)的注入:)但是,如果您有大量的應(yīng)用程序,那么花很多時(shí)間重寫所有類以使用構(gòu)造函數(shù)而不是setter并不是最好的主意。 幸運(yùn)的是,我有個(gè)好消息– AbstractRefreshableApplicationContext類中的allowCircularReferences字段。 只需添加一行到應(yīng)用程序上下文創(chuàng)建(所描述的方式在這個(gè)崗位 )
AnnotationConfigWebApplicationContext applicationContext =new AnnotationConfigWebApplicationContext(); applicationContext.setAllowCircularReferences(false); // rest of context initialization最后,為了使您心情愉快,我從DefaultListableBeanFactory粘貼了另一個(gè)代碼片段:
catch (NoSuchBeanDefinitionException ex) {// Shouldn't happen - probably a result of circular reference resolution...if (logger.isDebugEnabled()) {logger.debug("Failed to check manually registered singleton with name '"+ beanName + "'", ex);} }祝你今天愉快! :)
翻譯自: https://www.javacodegeeks.com/2015/01/dependency-injection-pitfalls-in-spring.html
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的Spring的依赖注入陷阱的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Hazelcast入门指南第5部分
- 下一篇: 抖音:发布 AI 生成、虚构情节等特定内