Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/387.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sqlite/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Spring依赖注入:如何基于系统属性实例化类?_Java_Spring - Fatal编程技术网

Java Spring依赖注入:如何基于系统属性实例化类?

Java Spring依赖注入:如何基于系统属性实例化类?,java,spring,Java,Spring,以这个例子为例 我有接口 interface FSClient String getMeData() 以及实现它的类 class MockFSClient implements FSClient { public String getMeData() { return “I am mock”; } } class RestFSClient implements FSClient { public String getMeData() { final Str

以这个例子为例

我有接口

interface FSClient
  String getMeData()
以及实现它的类

class MockFSClient implements FSClient {
  public String getMeData() {
    return “I am mock”;
  }
}



class RestFSClient implements FSClient {
  public String getMeData() {
    final String data = // from web service
    return data;
  }
}
还有一个看起来像

class FSManager {
  private FSClient fsclient;
  @Autowired
  public void FSManager(@Nonnull final FSClient fsClient) {
     this.fsclient = fsClient;
  }
}
我想基于系统属性实例化
fsclient

com.fs.mock=true
意思是如果
com.fs.mock=true
fsclient
应该是
MockFSClient
否则
fsclient
应该是
RestFSClient

我该怎么做

我为什么需要它?
这样我就可以解耦并进行测试

请帮助,我是Spring的新手

使用配置文件

...
    <beans profile="dev">
        <bean id="b1" class="MockFSClient" />
    </beans>

    <beans profile="uat,prod">
        <bean id="b1" class="RestFSClient" />
    </beans>
...
。。。
...

-Dspring.profiles.active=dev…

您是否在询问如何获得
com.fs.mock
的值,因为答案是使用
@value
注释和bean

如果您询问如何创建实际对象,那么正如@Jakkra所说,使用一个工厂,该工厂包含一个围绕
com.fs.mock
值的If语句。这不是最优雅的解决方案,但会奏效

范例

public class ClientFactory {
    @Value("${com.fs.mock}")
    private boolean mockFlag;

    public static returnClientInstance(){
        if(mockFlag){
            return new MockFSClient();
        }
        else{
            return new RestFSClient();
        }
    }
}

最好的方法可能是使用Evgeniy DOROFEV描述的概要文件,在这种情况下,您不需要自定义系统属性。但是,如果您使用条件Bean配置坚持自定义系统属性,那么这里有另一个解决方案

在这种方法中,您需要两个自定义条件来封装您的条件:

public class MockFSCondition implements Condition {

    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        String fsMockProperty = context.getEnvironment().getProperty("com.fs.mock");
        return fsMockProperty!=null && fsMockProperty.toLowerCase().equals("true");
    }
}

public class RestFSCondition implements Condition {

    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        String fsMockProperty = context.getEnvironment().getProperty("com.fs.mock");
        return fsMockProperty==null || !fsMockProperty.toLowerCase().equals("true");
    }
}
在这种情况下,您的配置类将如下所示:

@Configuration
@ComponentScan(basePackages = {"your.beans.package"})
public class Config {

    @Bean
    public FSClient mockFSClient(){
        return new MockFSClient();
    }

    @Bean
    public FSClient restFSClient(){
        return new RestFSClient();
    }

    @Bean(name="fsManager")
    @Conditional(MockFSCondition.class)
    public FSManager mockFsManager() {
        return new FSManager(mockFSClient());
    }


    @Bean(name="fsManager")
    @Conditional(RestFSCondition.class)
    public FSManager restFsManager() {
        return new FSManager(restFSClient());
    }
}
请注意,我们已经创建了两个同名的bean
fsManager
,每个bean都用上述两个条件进行了注释


因此,现在在运行时,Spring将查找该自定义系统道具,并给定它是否存在/正确,它将实例化正确版本的
FSManager
构造函数,注入正确的
FSClient

我将创建一个工厂,根据com.fs.mock=true创建不同的接口,然后返回没错。你只是问如何检索系统属性,对吗?我不能谈论使用完整注释配置,但是当使用XML配置时,您可以使用
${property}
符号检索系统属性的值。但是在
@Profile
的情况下,我还必须设置
spring.active.profiles
,是吗?是的,你确实会,但这不是一个定制的系统道具(所谓定制,我的意思是不绑定到你的特定应用程序,而是Spring主动寻找它)。