以编程方式解析Bean注入

时间:2017-10-25 09:37:29

标签: java spring spring-boot spring-profiles

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

帮助?

2 个答案:

答案 0 :(得分:1)

您可以将所有特定的解析器标记为@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");
}

答案 1 :(得分:0)

您可以激活多个配置文件,CH和IT,您的实施将失败。

这是一个国际化问题。