[英]Resolve Bean Injection Programmatically
你好,我想找到一種方法,以編程方式在 Spring 容器級別的 bean 工廠中存在的不同實現之間選舉候選人。
使用配置文件,我可以像這樣簡單地實現
我有以下配置文件“CH”和“IT”,我希望如果存在帶有 IT 的 Bean 配置文件,則將回退到默認值。
鑒於這些類:
默認實現
@Component
public class DefaultMapper {
public void doSomething() {
System.out.println("Map Default");
}
}
瑞士實施
@Component
@Profile("CH")
public class SwissMapper extends DefaultMapper {
@Override
public void doSomething() {
System.out.println("do something swiss");
}
}
意大利實施:
@Component
@Profile("IT")
public class ItalianMapper extends DefaultMapper {
@Override
public void doSomething() {
System.out.println("do pasta");
}
}
現在,如果我用@ActiveProfiles("IT")
運行它,它會拋出一個 NoUniqueBeanDefinitionException,這很公平,因為默認值沒有被分析,並且它將被注冊而不會受到容器的任何進一步關注。
一些考慮:
如果我將@Profile("default")
添加到DefaultMapper
這將起作用,直到我有另一個默認 bean 的子類僅使用 CH 進行了分析。
另一個 Bean 的默認實現:
@Component
@Profile("default")
public class DefaultParser {
public void doSomething() {
System.out.println("Parse Default");
}
}
然后是瑞士的實現(沒有意大利語可用,或者最好說默認適合意大利語):
@Component
@Profile("CH")
public class SwissParser extends DefaultParser {
@Override
public void doSomething() {
System.out.println("Ässe Ässe");
}
}
現在,如果我用@ActiveProfiles("IT")
運行它,它會拋出一個 No BeanDefinitionException,這足夠公平,但不是那么公平,因為“默認”沒有鏈接為 ActiveProfiles,對於 IT 我沒有實現。 此處的 CH 配置文件將起作用,因為每個默認類都有一個配置文件實現。
說我想要一種更好的方法來覆蓋這種情況,而無需: - 必須在默認類上定義,例如@Profile({"default","IT", "<all other profiles which have NOT a specialized implementation"}
,或@Profile("!CH")
其中我排除了那些具有專業化的配置文件。 - @Primary
我認為不是一個靈魂,因為在DefaultMapper
我必須專業化,它將被標記為@Primary
並且容器不喜歡它根本;)
然后我想解決這個問題,我可以決定所有注入的類,當 Bean 的解析不明確時,我想以編程方式決定(在容器中)我想選擇哪個實現。 我認為與 @Profile 類似的 Annotation ,iE @Candidate("CH") 與 iE nationality.cantidate=CH 中 application.properties 中設置的值相比更適合。 就像是:
public class MyExtension extends UnknowSpringType {
@Override
Object resolveAmbigousDependency(final Context ctx, final Resolution resolution) {
final List<Class> clazzes = resolution.getResolvedClasses();
for (final Class clazz : clazzes) {
if (clazz.isAnnotationPresent(Candidate.class) && clazz.getAnnotation(Candidate.class).getVaue().equals(candidateApplicationPropertyValue)) {
return clazz;
}
return getDefaultImplementation(clazzes);
}
}
我過去做過類似 CDI SPI 擴展的事情,非常優雅,我也可以用 CDI 的@Specializes
以另一種方式覆蓋這個,但我在 Spring 上找不到同樣簡單的方法(我沒有那么多經驗就可以了),BeanFactory? BeanFactoryPostProcessor ?
幫助 ?
您可以將所有特定的解析器標記為 @Primary,這將確保 Spring 自動裝配這個解析器,而不是未標記為 @Primary 的默認解析器。 當所選配置文件不存在特定解析器時,它將回退到非 @Primary 默認組件。
請參閱: https : //docs.spring.io/spring/docs/current/javadoc-api/org/springframework/context/annotation/Primary.html
@Component
public class DefaultParser {
public void doSomething() {
System.out.println("Parse Default");
}
}
@Component
@Primary
@Profile("CH")
public class SwissParser extends DefaultParser {
@Override
public void doSomething() {
System.out.println("Ässe Ässe");
}
您可以激活多個配置文件、CH 和 IT,您的實施將失敗。
這是一個國際化問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.