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());
}
}
请注意,我们已经创建了两个同名的beanfsManager
,每个bean都用上述两个条件进行了注释
因此,现在在运行时,Spring将查找该自定义系统道具,并给定它是否存在/正确,它将实例化正确版本的
FSManager
构造函数,注入正确的FSClient
我将创建一个工厂,根据com.fs.mock=true创建不同的接口,然后返回没错。你只是问如何检索系统属性,对吗?我不能谈论使用完整注释配置,但是当使用XML配置时,您可以使用${property}
符号检索系统属性的值。但是在@Profile
的情况下,我还必须设置spring.active.profiles
,是吗?是的,你确实会,但这不是一个定制的系统道具(所谓定制,我的意思是不绑定到你的特定应用程序,而是Spring主动寻找它)。