Ich habe eine Reihe von Spring Beans, die aus dem Klassenpfad über Annotationen abgeholt werden, z.B.
@Repository("personDao")
public class PersonDaoImpl extends AbstractDaoImpl implements PersonDao {
// Implementation omitted
}
In der Spring XML-Datei ist ein PropertyPlaceholderConfigurer definiert:
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="/WEB-INF/app.properties" />
</bean>
Ich möchte eine der Eigenschaften aus app.properites in die oben gezeigte Bean injizieren. Ich kann nicht einfach etwas tun wie
<bean class="com.example.PersonDaoImpl">
<property name="maxResults" value="${results.max}"/>
</bean>
Weil PersonDaoImpl nicht in der Spring-XML-Datei enthalten ist (es wird über Annotationen aus dem Klassenpfad geholt). Ich bin bis zum folgenden Punkt gekommen:
@Repository("personDao")
public class PersonDaoImpl extends AbstractDaoImpl implements PersonDao {
@Resource(name = "propertyConfigurer")
protected void setProperties(PropertyPlaceholderConfigurer ppc) {
// Now how do I access results.max?
}
}
Aber es ist mir nicht klar, wie ich auf die Eigenschaft zugreifen kann, an der ich von ppc
aus interessiert bin?
Eine andere Alternative ist das Hinzufügen der appProperties-Bean (siehe unten):
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="/WEB-INF/app.properties" />
</bean>
<bean id="appProperties"
class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="singleton" value="true"/>
<property name="properties">
<props>
<prop key="results.max">${results.max}</prop>
</props>
</property>
</bean>
Beim Abruf kann diese Bean in eine java.util.Properties
umgewandelt werden, die eine Eigenschaft namens results.max
enthält, deren Wert aus app.properties
gelesen wird. Auch diese Bean kann (als Instanz von java.util.Properties) über die @Resource-Annotation in eine beliebige Klasse injiziert werden.
Ich persönlich bevorzuge diese Lösung (gegenüber der anderen, die ich vorgeschlagen habe), da Sie genau festlegen können, welche Eigenschaften durch appProperties offengelegt werden, und app.properties nicht zweimal lesen müssen.
Ich muss zwei Eigenschaftsdateien haben, eine für die Produktion und eine Überschreibung für die Entwicklung (die nicht bereitgestellt wird).
Um beides zu haben, eine Properties Bean, die autowired sein kann, und einen PropertyConfigurer, kann man schreiben:
<bean id="appProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="singleton" value="true" />
<property name="ignoreResourceNotFound" value="true" />
<property name="locations">
<list>
<value>classpath:live.properties</value>
<value>classpath:development.properties</value>
</list>
</property>
</bean>
und die Properties Bean im PropertyConfigurer referenzieren
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="properties" ref="appProperties" />
</bean>
Eine mögliche Lösung besteht darin, eine zweite Bean zu deklarieren, die aus der gleichen Eigenschaftsdatei liest:
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="/WEB-INF/app.properties" />
</bean>
<util:properties id="appProperties" location="classpath:/WEB-INF/app.properties"/>
Die Bean mit dem Namen 'appProperties' ist vom Typ java.util.Properties und kann über das oben gezeigte @Resource-Attribut in die Abhängigkeit injiziert werden.