Hallo我想找到一种方法,以编程方式选择Bean工厂中存在的不同实现之间的候选者,在Spring Container Level。
使用Profiles我可以像这样实现
我有以下配置文件“CH”和“IT”,我希望如果有一个与IT配置的Bean,那么将回退到默认值。
鉴于这些课程:
默认实施
build:
script: python setup.py install --single-version-externally-managed--record=record.txt
瑞士实施
@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");
}
}
运行它,它会抛出一个NoUniqueBeanDefinitionException,这是公平的,因为Default没有被分析,并且它将在没有任何进一步关注的情况下被注册。
一些考虑因素:
如果我将@ActiveProfiles("IT")
添加到@Profile("default")
,这将有效,直到我有另一个默认bean只有CH的子类。
另一个Bean的默认实现:
DefaultMapper
然后瑞士实施(没有意大利语可用,或者更好地表示默认适合意大利语):
@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");
}
运行它会抛出No BeanDefinitionException,这是公平的,但不公平,因为“默认”不链接为ActiveProfiles而对于IT我没有实现。这里的CH配置文件将起作用,因为每个默认类都有一个配置文件实现。
说那个
我希望有一种更好的方法来覆盖这种情况,而无需:
- 必须在默认类上定义@ActiveProfiles("IT")
或@Profile({"default","IT", "<all other profiles which have NOT a specialized implementation"}
,其中i排除那些具有专业化的配置文件。
- @Profile("!CH")
我认为不是灵魂,因为在@Primary
我必须将专业化标记为DefaultMapper
且容器根本不喜欢它;)
然后 我想解决这个问题,我可以决定所有注入的类,当豆的分辨率是暧昧的时候,我想以编程方式决定(在容器中)我想选择哪个实现。我认为与@Profile相同的注释,i.E @Candidate(“CH”)将适合i.E nationality.cantidate = CH中application.properties中设置的值。类似的东西:
@Primary
我在过去做过与CDI SPI扩展类似的东西很优雅,而且我可以用CDI中的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);
}
}
以另一种方式覆盖它,但我在Spring上找不到相同的简单方法(i没有那么多经验),BeanFactory? BeanFactoryPostProcessor?
帮助?
答案 0 :(得分:1)
您可以将所有特定的解析器标记为@Primary,这将确保Spring自动装配此解析器而不是未标记为@Primary的默认解析器。如果所选配置文件不存在特定的解析器,则它将回退到非@Primary默认组件。
@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");
}
答案 1 :(得分:0)
您可以激活多个配置文件,CH和IT,您的实施将失败。
这是一个国际化问题。