2011-01-14 1 views
3

Mein spezifisches Problem ist, dass ich zwei Beans konfiguriert habe, die die gleiche Schnittstelle implementieren, und ich habe eine dritte Bean, die eine Eigenschaft des Typs dieser Schnittstelle hat. Ich injiziere die Eigenschaft mit einer Config-Eigenschaft. Also, vorausgesetzt RemoteDataSource und LocalDataSource IDataSource implementieren und dao1 hat eine Eigenschaft vom Typ IDataSource, könnte meine XML-Konfigurations wie folgt aussehen:Wie kann ich eine Autowired-Eigenschaft mit einer Variablen aus einer Konfigurationsdatei mithilfe von Anmerkungen qualifizieren?

<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> 

Mit url, filepath und Datenquelle in einer inkludierten Eigenschaften-Datei definiert werden. Wir machen nun einen Push für die Annotations-gesteuerte Konfiguration und ich bin mir nicht sicher, wie ich meinen Dao kommentieren soll, um die in der Eigenschaftendatei konfigurierte Datenquelle zu setzen. Ich möchte so etwas tun, aber es ist offensichtlich nicht erlaubt:

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

NB: Diese Feder 3

+4

Dies ist ein gutes Beispiel, denke ich, von einem Fall, wo Annotation Config nicht geeignet ist. XML und Annotationen arbeiten zusammen - nutzen Sie jedes für seine Stärken. – skaffman

Antwort

4

war meine Lösung:

@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); 
} 

NB: Ich änderte das zu DataProvider- Benennung von der kanonischen Datasource eindeutig zu machen, die dies nicht. Es ist eigentlich nur ein selbstgebauter REST-Client.

1

Ich glaube nicht, dies möglich ist. Sogar in CDI, das vollständig Annotations-getrieben ist, erfolgt das Wechseln der Beans abhängig von der Konfiguration über XML.

5

Haben Sie eine XML-Konfiguration? Ich nehme an, Sie tun, wie Sie eine Datenquelle haben.

Hard-Code der Qualifier für die Datenquelle und dann erstellen Sie einen Alias ​​in Ihrer XML-Konfiguration, die basierend auf der Eigenschaft Aliase.

So etwas wie

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

Und dann in xml:

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

Ich bin mir ziemlich sicher, dass die Feder Entwickler betrachtet so dass Sie es so, wie Sie angegeben haben zu tun, aber ich persönlich würde es vorziehen, nicht zu. Auszustrukturieren, wo es den $ dataSource-Wert bekommt, könnte ziemlich knifflig werden. Ich denke auch, dass das Unterstützen von konfigurierbaren Eigenschaften in Annotationen die Dinge zu sehr verkomplizieren und zu viel Verwirrung schaffen würde. so

1

Ich habe einige Arbeit für das ähnliche Problem, das ich hatte.

Mein Problem war, hatte ich drei Implementierung für den Service sagen ServiceImpl1, ServiceImpl2 und ServiceImpl3 und in der Eigenschaftendatei für Platzhalter my.serviceImpl I-Werte wie

my.serviceImpl = serviceImpl1 

oder

haben
my.serviceImpl = serviceImpl2 

oder

my.serviceImpl = serviceImpl3 

So in mein Controller sollte ich in der Lage sein @Qualifier ($ {my.my.serviceImpl}) zu verwenden, aber das hat nicht funktioniert, ich habe sogar @value versucht, aber es ist auch fehlgeschlagen.

Also endlich habe ich Bean in meiner ApplicationConf definiert.java als

@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(); 
     } 


} 

Und in meinem Controller verwendete ich Qualifier als

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

Nicht sicher aber, wenn dies der beste Weg, es zu tun ist.

0

für Frühling 3.1 Ihr Problem wird durch Spring profiles gelöst:

<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> 

Kein @Qualifier benötigt, nur ein IDataSource in jedem Profil.