3 Stimmen

Wie kann ich eine autowired-Eigenschaft mit einer Variablen aus einer Konfigurationsdatei mit Anmerkungen qualifizieren?

Mein spezifisches Problem ist, dass ich zwei Beans konfiguriert habe, die dieselbe Schnittstelle implementieren, und ich habe eine dritte Bean, die eine Eigenschaft vom Typ dieser Schnittstelle hat. Ich injiziere die Eigenschaft über eine Config-Eigenschaft. Angenommen, RemoteDataSource und LocalDataSource implementieren IDataSource und dao1 hat eine Eigenschaft vom Typ IDataSource, dann könnte meine XML-Konfiguration wie folgt aussehen:

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

Die URL, der Dateipfad und die Datenquelle werden in einer integrierten Eigenschaftsdatei definiert. Wir machen jetzt einen Vorstoß für annotationsgesteuerte Konfiguration und ich bin nicht sicher, wie ich mein Dao annotieren kann, um die Datenquelle in der Eigenschaftsdatei zu konfigurieren. Ich möchte so etwas tun, aber es ist offensichtlich nicht erlaubt:

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

NB: Dies ist der Frühling 3

5voto

Michael Wiles Punkte 20303

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

Geben Sie den Qualifier für die Datenquelle fest ein und erstellen Sie dann einen Alias in Ihrer XML-Konfiguration, der auf der Grundlage der Eigenschaft einen Alias erstellt.

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 Entwickler der Feder in Erwägung gezogen haben, Ihnen die Möglichkeit zu geben, es so zu machen, wie Sie es angegeben haben, aber ich persönlich würde es vorziehen, es nicht zu tun. Herauszufinden, woher der Wert $dataSource kommt, könnte ziemlich knifflig werden. Ich denke auch, dass die Unterstützung konfigurierbarer Eigenschaften in Annotationen die Dinge zu sehr verkomplizieren und zu viel potenzielle Verwirrung stiften würde.

4voto

jiggy Punkte 3778

Meine Lösung war also:

@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 diese Benennung in DataProvider, um von der kanonischen DataSource zu unterscheiden, die dies nicht ist. Es ist eigentlich nur ein hausgemachter REST-Client.

1voto

Bozho Punkte 570413

Ich glaube nicht, dass dies möglich ist. Sogar in CDI, das vollständig annotationsgesteuert ist, wird das Umschalten von Beans je nach Konfiguration über XML vorgenommen.

1voto

Pratik Goenka Punkte 2231

Für ein ähnliches Problem, das ich hatte, habe ich eine Lösung gefunden.

Mein Problem war, dass ich drei Implementierungen für den Dienst hatte, nämlich ServiceImpl1, ServiceImpl2 und ServiceImpl3, und in der Eigenschaftsdatei für den Platzhalter my.serviceImpl kann ich Werte haben wie

my.serviceImpl = serviceImpl1

o

my.serviceImpl = serviceImpl2

o

my.serviceImpl = serviceImpl3

In meinem Controller sollte ich also @Qualifier(${my.my.serviceImpl}) verwenden können. aber das hat nicht funktioniert, ich habe es sogar mit @value versucht, aber auch das ist fehlgeschlagen.

Schließlich definierte ich die Bohne in meiner ApplicationConf.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 habe ich den Qualifier als

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

Ich bin mir allerdings nicht sicher, ob dies der beste Weg ist.

1voto

Grigory Kislin Punkte 14348

Für Spring 3.1 wird Ihr Problem wie folgt gelöst Federprofile :

<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 erforderlich, nur eine IDataSource in jedem Profil.

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

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X