组件注入 # 注入的属性_注入域对象而不是基础结构组件
組件注入 # 注入的屬性
依賴注入是Java(以及許多其他編程語言)中廣泛使用的軟件設(shè)計(jì)模式,用于實(shí)現(xiàn)控制反轉(zhuǎn) 。 它提高了可重用性,可測試性,可維護(hù)性,并有助于構(gòu)建松耦合的組件。 如今,依賴注入是將Java對象連接在一起的事實(shí)上的標(biāo)準(zhǔn)。
諸如Spring或Guice之類的各種Java框架可以幫助實(shí)現(xiàn)依賴注入。 從Java EE 6開始,還有一個(gè)正式的Java EE API用于依賴關(guān)系注入: 上下文和依賴關(guān)系注入 (CDI)。
我們使用依賴注入來注入服務(wù),存儲庫,與域相關(guān)的組件,資源或配置值。 但是,以我的經(jīng)驗(yàn),依賴注入也可以用來注入域?qū)ο?#xff0c;這常常被忽略。
一個(gè)典型的例子是在Java許多應(yīng)用程序中獲取當(dāng)前登錄用戶的方式。 通常,我們最終會(huì)向登錄用戶詢問某些組件或服務(wù)。
此代碼看起來可能類似于以下代碼片段:
public?class?SomeComponent?{@Injectprivate?AuthService?authService;public?void?workWithUser()?{User?loggedInUser?=?authService.getLoggedInUser();//?do?something?with?loggedInUser} }此處,將AuthService實(shí)例注入SomeComponent。 SomeComponent的方法現(xiàn)在使用AuthService對象來獲取已登錄用戶的實(shí)例。
但是,除了注入AuthService之外,我們還可以將登錄的用戶直接注入SomeComponent。
可能看起來像這樣:
public?class?SomeComponent?{@Inject@LoggedInUserprivate?User?loggedInUser;public?void?workWithUser()?{//?do?something?with?loggedInUser} }在這里,User對象直接注入SomeComponent中,不需要AuthService實(shí)例。 如果存在多個(gè)類型為User的(托管)bean,則使用自定義批注@LoggedInUser來避免沖突。
Spring和CDI都可以進(jìn)行這種類型的注入(并且配置實(shí)際上非常相似)。 在下一節(jié)中,我們將看到如何使用Spring注入域?qū)ο蟆?在此之后,我將描述對CDI進(jìn)行相同操作需要進(jìn)行哪些更改。
使用Spring進(jìn)行域?qū)ο笞⑷?/h2>
要注入上面示例中所示的域?qū)ο?#xff0c;我們只需要做兩個(gè)小步驟。
首先,我們必須創(chuàng)建@LoggedInUser批注:
import?java.lang.annotation.*; import?org.springframework.beans.factory.annotation.Qualifier;@Target({ElementType.FIELD,?ElementType.PARAMETER,?ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Qualifier public?@interface?LoggedInUser?{}請注意@Qualifier批注,它將@LoggedInUser轉(zhuǎn)換為自定義限定符。 如果有多個(gè)相同類型的bean可用,Spring會(huì)使用限定符來避免沖突。
接下來,我們必須在我們的Spring配置中添加一個(gè)bean定義。 我們在這里使用Spring的Java配置,使用xml配置也可以完成。
@Configuration public?class?Application?{@Bean@LoggedInUser@Scope(value?=?WebApplicationContext.SCOPE_SESSION,?proxyMode?=?ScopedProxyMode.TARGET_CLASS)public?User?getLoggedInUser()?{//?retrieve?and?return?user?object?from?server/database/session} }在getLoggedInUser()內(nèi)部,我們必須檢索并返回當(dāng)前登錄用戶的實(shí)例(例如,通過從第一個(gè)片段中詢問AuthService)。 使用@Scope,我們可以控制返回對象的范圍。 最佳范圍取決于域?qū)ο?#xff0c;并且在不同的域?qū)ο笾g可能有所不同。 對于代表已登錄用戶的User對象, 請求或會(huì)話范圍將是有效的選擇。 通過用@LoggedInUser注釋getLoggedInUser(),我們告訴Spring應(yīng)該在每次注入用戶類型為@LoggedInUser的bean時(shí)使用此bean定義。
現(xiàn)在,我們可以將登錄用戶注入到其他組件中:
@Component public?class?SomeComponent?{@Autowired@LoggedInUserprivate?User?loggedInUser;... }在這個(gè)簡單的示例中,實(shí)際上不需要限定符注釋。 只要只有一個(gè)類型為User的bean定義可用,Spring可以按類型注入已登錄的用戶。 但是,在注入域?qū)ο髸r(shí),很容易發(fā)生您具有相同類型的多個(gè)bean定義。 因此,使用附加的限定符注釋是一個(gè)好主意。 限定符還可以使用其描述性名稱充當(dāng)文檔(如果命名正確)。
簡化Spring bean定義
注入許多域?qū)ο髸r(shí),最終有可能在bean配置中一遍又一遍地重復(fù)作用域和代理配置。 在這種情況下,Spring注釋可以在自定義注釋上使用非常方便。 因此,我們可以簡單地創(chuàng)建自己的@SessionScopedBean批注,以代替@Bean和@Scope:
@Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Bean @Scope(value?=?WebApplicationContext.SCOPE_SESSION,?proxyMode?=?ScopedProxyMode.TARGET_CLASS) public?@interface?SessionScopedBean?{}現(xiàn)在我們可以簡化bean的定義:
@Configuration public?class?Application?{@LoggedInUser@SessionScopedBeanpublic?User?getLoggedInUser()?{...} }Java EE和CDI
CDI的配置幾乎相同。 唯一的區(qū)別是我們必須用javax.inject和CDI注釋替換Spring注釋。
因此,@LoggedInUser應(yīng)該使用javax.inject.Qualifier而不是org.springframework.beans.factory.annotation.Qualifier進(jìn)行注釋(請參閱: 使用Qualifiers )。
Spring bean定義可以用CDI Producer方法代替。 可以使用適當(dāng)?shù)腃DI范圍注釋代替@Scope。
在注入點(diǎn),可以將Spring的@Autowired替換為@Inject。
請注意,Spring還支持javax.inject注釋。 如果將javax.inject依賴項(xiàng)添加到Spring項(xiàng)目中,則還可以使用@Inject和@ javax.inject.Qualifier。 這樣做實(shí)際上是一個(gè)好主意,因?yàn)樗梢詼p少Java代碼中的Spring依賴關(guān)系。
結(jié)論
我們可以使用自定義注釋和作用域bean將域?qū)ο笞⑷肫渌M件。 注入域?qū)ο罂梢允鼓拇a更易于閱讀,并且可以導(dǎo)致更清晰的依賴關(guān)系。 如果僅注入AuthService來獲取登錄用戶,則實(shí)際上取決于登錄用戶而不是AuthService。
不利的一面是,它使您的代碼更牢固地依賴于依賴注入框架,該框架必須為您管理bean范圍。 如果要保持在Dependency Injection容器之外使用類的能力,則可能會(huì)遇到問題。
哪種類型的域?qū)ο筮m合注入在很大程度上取決于您正在處理的應(yīng)用程序。 好的候選對象是您經(jīng)常使用的領(lǐng)域?qū)ο?#xff0c;并且不依賴于任何方法或請求參數(shù)。 當(dāng)前登錄的用戶是可能通常適合注入的對象。
- 您可以在GitHub上找到所示示例的源代碼。
翻譯自: https://www.javacodegeeks.com/2014/10/injecting-domain-objects-instead-of-infrastructure-components.html
組件注入 # 注入的屬性
總結(jié)
以上是生活随笔為你收集整理的组件注入 # 注入的属性_注入域对象而不是基础结构组件的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: openshift命令_使用命令行工具创
- 下一篇: 我国已具备航天员 180 天太空驻留失重