标签: spring-environment

动态注入spring bean

在java-spring网络应用程序中,我希望能够动态注入bean.例如,我有一个具有2种不同实现的接口:

在此输入图像描述

在我的应用程序中,我正在使用一些属性文件来配置注入:

#Determines the interface type the app uses. Possible values: implA, implB
myinterface.type=implA
Run Code Online (Sandbox Code Playgroud)

我的注入实际上有条件地在属性文件中的属性值上加载.例如,在这种情况下myinterface.type = implA,只要我注入MyInterface,将注入的实现将是ImplA(我通过扩展条件注释完成了).

我希望在运行时 - 一旦属性发生更改,将发生以下情况(无需重新启动服务器):

  1. 将注入正确的实施方案.例如,设置myinterface.type=implBImplB将被注入到使用MyInterface的地方
  2. 应该使用新值刷新Spring Environment并重新注入bean.

我想要刷新我的上下文,但这会产生问题.我想可能会使用setter进行注入,并在重新配置属性后重新使用这些setter.是否有这种要求的工作实践?

有任何想法吗?

UPDATE

正如一些人所建议我可以使用一个工厂/注册表来保存两个实现(ImplA和ImplB)并通过查询相关属性返回正确的实现.如果我这样做,我还有第二个挑战 - 环境.例如,如果我的注册表看起来像这样:

@Service
public class MyRegistry {

private String configurationValue;
private final MyInterface implA;
private final MyInterface implB;

@Inject
public MyRegistry(Environmant env, MyInterface implA, MyInterface ImplB) {
        this.implA = implA;
        this.implB = implB;
        this.configurationValue = env.getProperty("myinterface.type");
}

public MyInterface getMyInterface() {
        switch(configurationValue) {
        case "implA":
                return implA; …
Run Code Online (Sandbox Code Playgroud)

java polymorphism spring spring-environment

25
推荐指数
5
解决办法
3万
查看次数

在xml中定义Spring @PropertySource并在Environment中使用它

在Spring JavaConfig中,我可以定义属性源并注入到Environment中

@PropertySource("classpath:application.properties")

@Inject private Environment environment;
Run Code Online (Sandbox Code Playgroud)

如果在xml中我该怎么做?我使用context:property-placeholder,并在JavaConfig类@ImportResource上导入xml.但我无法使用environment.getProperty("xx")检索属性文件中定义的属性

<context:property-placeholder location="classpath:application.properties" />
Run Code Online (Sandbox Code Playgroud)

java spring properties spring-environment

17
推荐指数
1
解决办法
1万
查看次数

使用常量解析属性时如何在@Value中使用Spring-EL

我正在尝试使用常量来定义属性,然后使用@Value注释解析它.

我在接口中定义了常量:

public interface InternalConstant{
   public static final String JOB_NAME_PROPERTY = "javabatch.jobName";
}
Run Code Online (Sandbox Code Playgroud)

我正在使用springboot,我将该属性作为默认属性添加到上下文中:

SpringApplication springApp = new SpringApplication(configs.toArray());
Properties props = new Properties();
props.setProperty(InternalConstants.JOB_NAME_PROPERTY, "MyStartableJob");
springApp.setDefaultProperties(props);
Run Code Online (Sandbox Code Playgroud)

现在,我想使用@Value将String"MyStartableJob"注入String.但是@Value(value="${javabatch.jobName})我不想直接使用,而是想使用定义的常量.

我试过了

@Value(value="#{T(ch.mobi.javabatch.core.internal.InternalConstants).JOB_NAME_PROPERTY}")
Run Code Online (Sandbox Code Playgroud)

但是,当然,这只解析为"javabatch.jobName"而不是名为"javabatch.jobName"的属性的值.

所以我尝试将其包装@Value(value="${#{T(ch.mobi.javabatch.core.internal.InternalConstants).JOB_NAME_PROPERTY}}"),但这会导致异常.

Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder '#{T(ch.mobi.javabatch.core.internal.InternalConstants).JOB_NAME_PROPERTY}' in string value "${#{T(ch.mobi.javabatch.core.internal.InternalConstants).JOB_NAME_PROPERTY}}"
    at org.springframework.util.PropertyPlaceholderHelper.parseStringValue(PropertyPlaceholderHelper.java:174)
    at org.springframework.util.PropertyPlaceholderHelper.replacePlaceholders(PropertyPlaceholderHelper.java:126)
    at org.springframework.core.env.AbstractPropertyResolver.doResolvePlaceholders(AbstractPropertyResolver.java:204)
    at org.springframework.core.env.AbstractPropertyResolver.resolveRequiredPlaceholders(AbstractPropertyResolver.java:178)
    at org.springframework.context.support.PropertySourcesPlaceholderConfigurer$2.resolveStringValue(PropertySourcesPlaceholderConfigurer.java:175)
    at org.springframework.beans.factory.support.AbstractBeanFactory.resolveEmbeddedValue(AbstractBeanFactory.java:801)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:955)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:942)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:533)
    ... 16 more
Run Code Online (Sandbox Code Playgroud)

我知道,我可以简单地注入Environment并使用其getProperty方法:

@Autowired
private Environment env;

public void m1() {
    env.getProperty(InternalConstants.JOB_NAME_PROPERTY);
} …
Run Code Online (Sandbox Code Playgroud)

spring spring-el spring-environment spring-boot

6
推荐指数
1
解决办法
5949
查看次数

将 &lt;property-placeholder&gt; 属性暴露给 Spring Environment

我有一个属性文件,我使用以下property-placeholder元素通过 XML 向 Spring 注册:

<context:property-placeholder location="classpath:foo.properties" />
Run Code Online (Sandbox Code Playgroud)

我可以使用@Value注释访问属性,例如

@Value("${prefs.key}")
private String prefValue;
Run Code Online (Sandbox Code Playgroud)

但我还需要通过 Spring Environment 访问属性,例如

@Autowired
private Environment env;

public String getValue(String key) {
  return env.getProperty(key);
}
Run Code Online (Sandbox Code Playgroud)

getValue()这里总是返回null,即使对于属性文件中定义的键也是如此,因为 using<property-placeholder>似乎不会向环境公开属性。有没有办法强制以这种方式加载的属性可以通过环境访问?

java spring properties-file spring-environment

5
推荐指数
1
解决办法
2284
查看次数