如何使用注释从配置文件中使用变量限定autowired属性?

时间:2011-01-14 22:49:04

标签: java spring annotations

我的具体问题是我已经配置了两个实现相同接口的bean,并且我有一个第三个bean,它具有该接口类型的属性。我使用config属性注入属性。因此,假设RemoteDataSource和LocalDataSource实现IDataSource并且dao1具有IDataSource类型的属性,我的XML配置可能如下所示:

<bean id="datasource1" class="com.foo.RemoteDataSource">
  <property name="url">${url}</property>
</bean>
<bean id="datasource2" class="com.foo.LocalDataSource">
  <property name="path">${filepath}</property>
</bean>
<bean id="dao1" class="com.foo.MyDAO">
  <property name="dataSource">${datasource}</property>
</bean>

在包含的属性文件中定义url,filepath和datasource。我们现在正在推动注释驱动的配置,并且我不确定如何注释我的dao以将数据源配置在属性文件中。我想做这样的事情,但显然不允许:

@Autowired
@Qualifier("${datasource}")
public void setDataSource(IDataSource datasource) {...}

注意:这是春天3

5 个答案:

答案 0 :(得分:5)

你有任何xml配置吗?我假设你有一个数据源。

对数据源的限定符进行硬编码,然后在xml配置中创建别名,该别名基于属性别名。

这样的东西
@Autowired
@Qualifier("designatedDatasource")
public void setDataSource(IDataSource datasource) {...}

然后在xml:

<alias name="${dataSource}" alias="designatedDatasource"/>

我很确定春天的开发者会考虑允许你按照你指定的方式去做,但就个人而言,我宁愿不这样做。解决它从哪里获得$ dataSource值可能会变得非常棘手。我还认为,在注释中支持可配置属性会使事情变得过于复杂,并且会产生太多潜在的混淆。

答案 1 :(得分:4)

我的解决方案是:

@Autowired
public void setDataProviders(Map<String,IDataProvider> dataProviders) {
    this.dataProviders = dataProviders;
}

@Autowired
@Value("${cms}")
public void setDataProviderName(String dataProviderName) {
    this.dataProviderName = dataProviderName;
}

public IDataProvider getDataProvider() {
    return dataProviders.get(dataProviderName);
}

注意:我将该命名更改为DataProvider,以消除规范DataSource的歧义,而不是。它实际上只是一个自制的REST客户端。

答案 2 :(得分:1)

我不认为这是可能的。即使在完全由注释驱动的CDI中,依赖于配置的切换bean也是通过xml完成​​的。

答案 3 :(得分:1)

我做了一些解决我遇到的类似问题的工作。

我的问题是我有三个服务实现说ServiceImpl1,ServiceImpl2和ServiceImpl3和 在占位符my.serviceImpl的属性文件中,我可能有像

这样的值
my.serviceImpl = serviceImpl1

my.serviceImpl = serviceImpl2

my.serviceImpl = serviceImpl3

所以在我的控制器中我应该可以使用@Qualifier($ {my.my.serviceImpl}) 但是这没用,我甚至尝试了@value但它也失败了。

所以最后我在我的ApplicationConf.java中将bean定义为

@Bean(name = "myServiceImpl")
public Service myService() {

    String beanName = environment.getProperty("my.serviceImpl");

        if (beanName.equals("serviceImpl1")) {
            return new serviceImpl1();
        }
        else if(beanName.equals("serviceImpl2")){
            return new serviceImpl2();
        }
        else if(beanName.equals("serviceImpl3")){
            return new serviceImpl3();
        }


}

在我的控制器中,我使用限定符作为

@Autowired
@Qualifier("myServiceImpl")
Service myService;

不确定这是否是最好的方法。

答案 4 :(得分:0)

对于Spring 3.1,您的问题由Spring profiles解决:

<bean id="dao1" class="com.foo.MyDAO">
   <property name="dataSource">${datasource}</property>
</bean>

<beans profile="remote">
   <bean id="datasource1" class="com.foo.RemoteDataSource">
      <property name="url">${url}</property>
   </bean>
<beans>

<beans profile="local">
    <bean id="datasource2" class="com.foo.LocalDataSource">
      <property name="path">${filepath}</property>
    </bean>
<beans>

不需要@Qualifier,每个配置文件中只有一个IDataSource。

@Autowired
public void setDataSource(IDataSource datasource) {...}