Tengo un montón de beans de Spring que se recogen del classpath mediante anotaciones, por ejemplo
@Repository("personDao")
public class PersonDaoImpl extends AbstractDaoImpl implements PersonDao {
// Implementation omitted
}
En el archivo XML de Spring, hay un PropertyPlaceholderConfigurer definido:
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="/WEB-INF/app.properties" />
</bean>
Quiero inyectar una de las propiedades de app.properites en el bean mostrado arriba. No puedo simplemente hacer algo como
<bean class="com.example.PersonDaoImpl">
<property name="maxResults" value="${results.max}"/>
</bean>
Porque PersonDaoImpl no aparece en el archivo XML de Spring (se recoge del classpath mediante anotaciones). He llegado hasta lo siguiente:
@Repository("personDao")
public class PersonDaoImpl extends AbstractDaoImpl implements PersonDao {
@Resource(name = "propertyConfigurer")
protected void setProperties(PropertyPlaceholderConfigurer ppc) {
// Now how do I access results.max?
}
}
Pero no me queda claro cómo accedo a la propiedad que me interesa desde ppc
.
Otra alternativa es añadir el bean appProperties que se muestra a continuación:
<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>
Cuando se recupera, este bean se puede convertir en un java.util.Properties
que contendrá una propiedad llamada results.max
cuyo valor se lee de app.properties
. De nuevo, este bean puede ser inyectado en dependencia (como una instancia de java.util.Properties) en cualquier clase a través de la anotación @Resource.
Personalmente, prefiero esta solución (a la otra que propuse), ya que puedes limitar exactamente qué propiedades son expuestas por appProperties, y no necesitas leer app.properties dos veces.
Necesito tener dos archivos de propiedades, uno para producción y otro para desarrollo (que no se desplegará).
Para tener ambos, un Bean Properties que se pueda autocablear y un PropertyConfigurer, se puede escribir:
<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>
y referenciar el Properties Bean en el PropertyConfigurer
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="properties" ref="appProperties" />
</bean>
Una posible solución es declarar un segundo bean que lea del mismo archivo de propiedades:
<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"/>
El bean llamado 'appProperties' es de tipo java.util.Properties y puede ser inyectado en dependencia usando el atruibuto @Resource mostrado arriba.