javascript
spring 注释的作用_Spring的@Primary注释在起作用
spring 注釋的作用
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']} }測試非常簡單:
每個模塊的功能
想象一下您在核心模塊中定義了接口的實現的情況。
@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存儲庫中找到此處提供的代碼。
翻譯自: https://www.javacodegeeks.com/2013/12/springs-primary-annotation-in-action.html
spring 注釋的作用
總結
以上是生活随笔為你收集整理的spring 注释的作用_Spring的@Primary注释在起作用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 电脑符号的问号怎么打(电脑中的问号怎么打
- 下一篇: 小米11配置参数详情(小米11参数配置表