日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

Spring的@Primary注释在起作用

發布時間:2023/12/3 javascript 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Spring的@Primary注释在起作用 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Spring是一個永不止息的框架。 這是因為它提供了許多不同的解決方案,使我們(開發人員)無需編寫數百萬行代碼即可完成我們的任務。 取而代之的是,我們能夠以更具可讀性,更標準化的方式進行操作。 在這篇文章中,我將嘗試描述最有可能為大家所熟知的功能之一,但我認為其重要性被低估了。 我將要討論的功能是@Primary批注。

問題

在我從事的幾個項目中,我們遇到了一個常見的業務問題–我們有一個進入更復雜邏輯的入口–一些容器,該容器會將其他幾個處理器的結果收集到一個輸出中(例如map-filter-reduce函數編程中的函數)。 在某種程度上,它類似于Composite模式。 綜上所述,我們的方法如下:

  • 我們有一個容器,其中包含自動實現共同接口的處理器列表
  • 我們的容器實現了與自動裝配列表元素相同的接口
  • 我們希望使用該容器的客戶端類使整個處理工作透明化-他只對結果感興趣
  • 處理器具有一些邏輯(謂詞),處理器可將其應用于當前輸入數據集
  • 然后將處理結果合并到一個列表中,然后縮減為單個輸出
  • 有很多方法可以解決此問題-我將介紹一種使用Spring和@Primary批注的方法。

    解決方案

    讓我們從定義用例如何適應上述前提開始。 我們的數據集是一個Person類,如下所示:

    人.java

    package com.blogspot.toomuchcoding.person.domain;public final class Person {private final String name;private final int age;private final boolean stupid;public Person(String name, int age, boolean stupid) {this.name = name;this.age = age;this.stupid = stupid;}public String getName() {return name;}public int getAge() {return age;}public boolean isStupid() {return stupid;} }

    沒有什么不尋常的。 現在讓我們定義合同:

    PersonProcessingService.java

    package com.blogspot.toomuchcoding.person.service;import com.blogspot.toomuchcoding.person.domain.Person;public interface PersonProcessingService {boolean isApplicableFor(Person person);String process(Person person); }

    如前提條件所述,PersonProcessingService的每個實現都必須定義合同的兩點:

  • 是否適用于當前人員
  • 它如何處理一個人。
  • 現在,讓我們看一下我們擁有的一些處理器-由于它毫無意義,所以我不會在此處發布代碼-您可以稍后在Github或Bitbucket上查看代碼。 我們有以下@Component注釋的PersonProcessingService實現:

    • AgePersonProcessingService
      • 如果某人的年齡大于或等于18,則適用
    • IntelligencePersonProcessingService
      • 適用于某人是愚蠢的人
    • NamePersonProcessingService
      • 如果某人有名字,則適用

    邏輯很簡單。 現在,我們的PersonProcessingServices容器將要針對處理器上的給定Person進行迭代,檢查當前處理器是否適用(過濾器),如果是這種情況,則將響應處理Person的結果字符串添加到響應列表中(映射-將Person轉換為String的函數),并最終以逗號將這些響應合并(減少)。 讓我們檢查一下它是如何完成的:

    PersonProcessingServiceContainer.java

    package com.blogspot.toomuchcoding.person.service;import java.util.ArrayList; import java.util.List;import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Component;import com.blogspot.toomuchcoding.person.domain.Person;@Component @Primary class PersonProcessingServiceContainer implements PersonProcessingService {private static final Logger LOGGER = LoggerFactory.getLogger(PersonProcessingServiceContainer.class);@Autowiredprivate List<PersonProcessingService> personProcessingServices = new ArrayList<PersonProcessingService>();@Overridepublic boolean isApplicableFor(Person person) {return person != null;}@Overridepublic String process(Person person) {List<String> output = new ArrayList<String>();for(PersonProcessingService personProcessingService : personProcessingServices){if(personProcessingService.isApplicableFor(person)){output.add(personProcessingService.process(person));}}String result = StringUtils.join(output, ",");LOGGER.info(result);return result;}public List<PersonProcessingService> getPersonProcessingServices() {return personProcessingServices;} }

    如您所見,我們有一個用@Primary注釋的容器,這意味著如果必須注入PersonProcessingService的實現,則Spring將選擇要注入的PersonProcessingServiceContainer。 很棒的事情是,我們有一個自動連接的PersonProcessingServices列表,這意味著該接口的所有其他實現都將在那里自動連接(容器不會自動將其自身連接到該列表!)。

    現在,讓我們檢查一下Spock測試 ,這些測試證明我沒有在說謊。 如果您尚未在項目中使用Spock,則應立即將其移動。

    PersonProcessingServiceContainerIntegrationSpec.groovy

    package com.blogspot.toomuchcoding.person.service import com.blogspot.toomuchcoding.configuration.SpringConfiguration import com.blogspot.toomuchcoding.person.domain.Person import org.springframework.beans.factory.annotation.Autowired import org.springframework.test.context.ContextConfiguration import spock.lang.Specification import spock.lang.Unrollimport static org.hamcrest.CoreMatchers.notNullValue@ContextConfiguration(classes = [SpringConfiguration]) class PersonProcessingServiceContainerIntegrationSpec extends Specification {@AutowiredPersonProcessingService personProcessingServicedef "should autowire container even though there are many implementations of service"(){ expect: personProcessingService instanceof PersonProcessingServiceContainer}def "the autowired container should not have itself in the list of autowired services"(){ expect: personProcessingService instanceof PersonProcessingServiceContainerand:!(personProcessingService as PersonProcessingServiceContainer).personProcessingServices.findResult {it instanceof PersonProcessingServiceContainer}}def "should not be applicable for processing if a person doesn't exist"(){given:Person person = nullexpect:!personProcessingService.isApplicableFor(person)}def "should return an empty result for a person not applicable for anything"(){given:Person person = new Person("", 17, false)when:def result = personProcessingService.process(person)then:result notNullValue()result.isEmpty()}@Unroll("For name [#name], age [#age] and being stupid [#stupid] the result should contain keywords #keywords")def "should perform different processing depending on input"(){given:Person person = new Person(name, age, stupid)when:def result = personProcessingService.process(person) then:keywords.every {result.contains(it) }where:name | age | stupid || keywords"jan" | 20 | true || ['NAME', 'AGE', 'STUPID']"" | 20 | true || ['AGE', 'STUPID']"" | 20 | false || ['AGE']null | 17 | true || ['STUPID']"jan" | 17 | true || ['NAME']} }

    測試非常簡單:

  • 我們證明自動裝配字段實際上是我們的容器– PersonProcessingServiceContainer。
  • 然后,我們證明在PersonProcessingService的自動裝配實現的集合中找不到對象,該對象屬于PersonProcessingServiceContainer類型
  • 在接下來的兩個測試中,我們證明處理器背后的邏輯正在運行
  • 最后但并非最不重要的一點是Spock最出色的– where子句,它使我們能夠創建漂亮的參數化測試。
  • 每個模塊的功能

    想象一下您在核心模塊中定義了接口的實現的情況。

    @Component class CoreModuleClass implements SomeInterface { ... }

    如果您在與核心模塊有依賴性的其他模塊中決定不想使用此CoreModuleClass并希望在SomeInterface自動連線的任何地方都具有一些自定義邏輯該怎么辦? 好吧–使用@Primary!

    @Component @Primary class CountryModuleClass implements SomeInterface { ... }

    通過這種方式,您可以確保必須自動裝配SomeInterface的位置將是您的CountryModuleClass,將其插入到該字段中。

    結論

    在這篇文章中,您可以看到如何

    • 使用@Primary批注創建類似接口實現的復合容器
    • 使用@Primary批注提供接口的每個模塊實現,在自動裝配方面,該實現將優先于其他@Components
    • 編寫出色的Spock測試:)

    編碼

    您可以在Too Much Coding的Github存儲庫或Too Much Coding的Bitbucket存儲庫中找到此處提供的代碼。

    參考:來自我們的JCG合作伙伴 Marcin Grzejszczak(位于Blog上)的 Spring @Primary注釋 適用于編碼成癮者博客。

    翻譯自: https://www.javacodegeeks.com/2013/12/springs-primary-annotation-in-action.html

    總結

    以上是生活随笔為你收集整理的Spring的@Primary注释在起作用的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。