Как я могу ввести значение свойства в Spring Bean, который был настроен с помощью аннотаций?
у меня есть куча весенних бобов, которые подобраны из classpath через аннотации, например
@Repository("personDao")
public class PersonDaoImpl extends AbstractDaoImpl implements PersonDao {
// Implementation omitted
}
в весеннем XML-файле есть PropertyPlaceholderConfigurer определил:
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="/WEB-INF/app.properties" />
</bean>
Я хочу ввести одно из свойств из приложения.свойства в зернах показано выше. Я не могу просто сделать что-то вроде
<bean class="com.example.PersonDaoImpl">
<property name="maxResults" value="${results.max}"/>
</bean>
потому что PersonDaoImpl не имеет функции в файле Spring XML (он берется из пути к классам через комментарии.) Я дошел до следующего:
@Repository("personDao")
public class PersonDaoImpl extends AbstractDaoImpl implements PersonDao {
@Resource(name = "propertyConfigurer")
protected void setProperties(PropertyPlaceholderConfigurer ppc) {
// Now how do I access results.max?
}
}
но мне не ясно, как я получаю доступ к интересующему меня имуществу от ppc?
17 ответов:
вы можете сделать это весной 3 с помощью поддержки EL. Пример:
@Value("#{systemProperties.databaseName}") public void setDatabaseName(String dbName) { ... } @Value("#{strategyBean.databaseKeyGenerator}") public void setKeyGenerator(KeyGenerator kg) { ... }
systemPropertiesявляется неявным объектом иstrategyBean- это название фасоли.еще один пример, который работает, когда вы хотите, чтобы захватить собственность от
лично я люблю этот новый способ весной 3.0 документы:
private @Value("${propertyName}") String propertyField;нет геттеров или сеттеров!
при загрузке свойств через конфигурацию:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" p:location="classpath:propertyFile.properties" name="propertiesBean"/>для дальнейшего моего ликования я даже могу управлять щелчком по выражению EL в IntelliJ, и это приводит меня к определению свойства!
есть также полностью не xml версия:
@PropertySource("classpath:propertyFile.properties") public class AppConfig { @Bean public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() { return new PropertySourcesPlaceholderConfigurer(); }
появилась новая аннотация
@Valueна Весна 3.0. 0M3.@Valueподдержка не только#{...}выражения, но${...}заполнители, а также
<context:property-placeholder ... />является XML-эквивалентом PropertyPlaceholderConfigurer.пример: applicationContext.xml
<context:property-placeholder location="classpath:test.properties"/>компонент класс
private @Value("${propertyName}") String propertyField;
Другой альтернативой является добавление компонента appProperties, показанного ниже:
<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>при извлечении этот боб может быть приведен к
java.util.Properties, который будет содержать свойство с именемresults.maxзначение которого считывается сapp.properties. Опять же, этот компонент может быть введен в зависимость (как экземпляр java.утиль.Свойствами) в любой класс через аннотацию @Resource.лично я предпочитаю это решение (к другому я предложил), так как вы можете ограничить точно, какие свойства подвергаются по appProperties, и не нужно читать приложение.свойства дважды.
мне нужно иметь два файла свойств, для производства и переопределение для развития (что не будет развернут).
чтобы иметь оба, свойства Боба, который может быть autowired и PropertyConfigurer, вы можете написать:
<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>и ссылаться на свойства Bean в PropertyConfigurer
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="properties" ref="appProperties" /> </bean>
прежде чем мы получим Spring 3 - который позволяет вводить константы свойств непосредственно в ваши бобы с помощью аннотаций - я написал подкласс компонента PropertyPlaceholderConfigurer, который делает то же самое. Таким образом, вы можете пометить свои сеттеры свойств, и Spring автоматически подключит ваши свойства к вашим бобам следующим образом:
@Property(key="property.key", defaultValue="default") public void setProperty(String property) { this.property = property; }Аннотация выглядит следующим образом:
@Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD, ElementType.FIELD}) public @interface Property { String key(); String defaultValue() default ""; }свойство Annotationandplaceholderconfigurer имеет вид следует:
public class PropertyAnnotationAndPlaceholderConfigurer extends PropertyPlaceholderConfigurer { private static Logger log = Logger.getLogger(PropertyAnnotationAndPlaceholderConfigurer.class); @Override protected void processProperties(ConfigurableListableBeanFactory beanFactory, Properties properties) throws BeansException { super.processProperties(beanFactory, properties); for (String name : beanFactory.getBeanDefinitionNames()) { MutablePropertyValues mpv = beanFactory.getBeanDefinition(name).getPropertyValues(); Class clazz = beanFactory.getType(name); if(log.isDebugEnabled()) log.debug("Configuring properties for bean="+name+"["+clazz+"]"); if(clazz != null) { for (PropertyDescriptor property : BeanUtils.getPropertyDescriptors(clazz)) { Method setter = property.getWriteMethod(); Method getter = property.getReadMethod(); Property annotation = null; if(setter != null && setter.isAnnotationPresent(Property.class)) { annotation = setter.getAnnotation(Property.class); } else if(setter != null && getter != null && getter.isAnnotationPresent(Property.class)) { annotation = getter.getAnnotation(Property.class); } if(annotation != null) { String value = resolvePlaceholder(annotation.key(), properties, SYSTEM_PROPERTIES_MODE_FALLBACK); if(StringUtils.isEmpty(value)) { value = annotation.defaultValue(); } if(StringUtils.isEmpty(value)) { throw new BeanConfigurationException("No such property=["+annotation.key()+"] found in properties."); } if(log.isDebugEnabled()) log.debug("setting property=["+clazz.getName()+"."+property.getName()+"] value=["+annotation.key()+"="+value+"]"); mpv.addPropertyValue(property.getName(), value); } } for(Field field : clazz.getDeclaredFields()) { if(log.isDebugEnabled()) log.debug("examining field=["+clazz.getName()+"."+field.getName()+"]"); if(field.isAnnotationPresent(Property.class)) { Property annotation = field.getAnnotation(Property.class); PropertyDescriptor property = BeanUtils.getPropertyDescriptor(clazz, field.getName()); if(property.getWriteMethod() == null) { throw new BeanConfigurationException("setter for property=["+clazz.getName()+"."+field.getName()+"] not available."); } Object value = resolvePlaceholder(annotation.key(), properties, SYSTEM_PROPERTIES_MODE_FALLBACK); if(value == null) { value = annotation.defaultValue(); } if(value == null) { throw new BeanConfigurationException("No such property=["+annotation.key()+"] found in properties."); } if(log.isDebugEnabled()) log.debug("setting property=["+clazz.getName()+"."+field.getName()+"] value=["+annotation.key()+"="+value+"]"); mpv.addPropertyValue(property.getName(), value); } } } } } }не стесняйтесь изменять по вкусу
вы также можете комментировать твои занятия:
@PropertySource("classpath:/com/myProject/config/properties/database.properties")и есть переменная, как это:
@Autowired private Environment env;Теперь вы можете получить доступ ко всем вашим свойствам таким образом:
env.getProperty("database.connection.driver")
источник:
private @Value("${propertyName}") String propertyField;это новый способ ввести значение с помощью класса Spring "PropertyPlaceholderConfigurer". Другой способ-позвонить
java.util.Properties props = System.getProperties().getProperty("propertyName");Примечание: Для @Value, вы не можете использовать статический propertyField, она должна быть не только статической, в противном случае он возвращает значение null. Чтобы исправить это, для статического поля создается нестатический сеттер, а над этим сеттером применяется @Value.
возможным решением является объявление второго компонента, который читает из того же файла свойств:
<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"/>боб с именем 'appProperties' имеет тип java.утиль.Свойства и может быть зависимость вводится с помощью @Resource attruibute показано выше.
Если вы застряли с помощью Spring 2.5, вы можете определить боб для каждого из ваших свойств и ввести их с помощью квалификаторов. Вот так:
<bean id="someFile" class="java.io.File"> <constructor-arg value="${someFile}"/> </bean>и
@Service public class Thing public Thing(@Qualifier("someFile") File someFile) { ...его не очень читаемый, но он получает работу.
как уже упоминалось
@Valueделает работу, и это довольно гибкий, как вы можете иметь spring EL в нем.вот несколько примеров, которые могут быть полезны:
//Build and array from comma separated parameters //Like currency.codes.list=10,11,12,13 @Value("#{'${currency.codes.list}'.split(',')}") private List<String> currencyTypes;еще один, чтобы получить
setСlist//If you have a list of some objects like (List<BranchVO>) //and the BranchVO has areaCode,cityCode,... //You can easily make a set or areaCodes as below @Value("#{BranchList.![areaCode]}") private Set<String> areas;можно также задать значения для примитивных типов.
@Value("${amount.limit}") private int amountLimit;вы можете вызвать статические методы:
@Value("#{T(foo.bar).isSecurityEnabled()}") private boolean securityEnabled;вы можете иметь логику
@Value("#{T(foo.bar).isSecurityEnabled() ? '${security.logo.path}' : '${default.logo.path}'}") private String logoPath;
Autowiring значения свойств в Spring Beans:
большинство людей знают, что вы можете использовать @Autowired, чтобы сказать Spring, чтобы ввести один объект в другой, когда он загружает контекст приложения. Менее известный самородок информации заключается в том, что вы также можете использовать аннотацию @Value для вставки значений из файла свойств в атрибуты компонента. см. Этот пост для получения дополнительной информации...
новый материал весной 3.0 | / autowiring bean значения | / autowiring значения свойств весной
для меня это был ответ @Lucky, а конкретно, строка
AutowiredFakaSource fakeDataSource = ctx.getBean(AutowiredFakaSource.class);это исправило мою проблему. У меня есть приложение на основе ApplicationContext, работающее из командной строки, и, судя по ряду комментариев на SO, Spring подключает их по-разному к приложениям на основе MVC.
Если вам нужна большая гибкость для конфигураций, попробуйте Settings4jPlaceholderConfigurer: http://settings4j.sourceforge.net/currentrelease/configSpringPlaceholder.html
в нашем приложении мы используем:
- настройки для настройки PreProd-и Prod-системы
- настройки и переменные среды JNDI (JNDI перезаписывает настройки) для "mvn jetty: run"
- системные свойства для UnitTests (@BeforeClass аннотация)
порядок по умолчанию, в котором ключ-значение-источник проверяется первым, описан в:
http://settings4j.sourceforge.net/currentrelease/configDefault.html
Его можно подгонять с a settings4j.xml (с точностью до log4j.xml) в вашем classpath.Дайте мне знать Ваше мнение: [email protected]
с наилучшими пожеланиями,
Харальд
Я думаю, что это самый удобный способ ввести свойства в bean-это метод setter.
пример:
package org.some.beans; public class MyBean { Long id; String name; public void setId(Long id) { this.id = id; } public Long getId() { return id; } public void setName(String name) { this.name = name; } public String getName() { return name; } }определение XML Bean:
<bean id="Bean1" class="org.some.beans.MyBean"> <property name="id" value="1"/> <property name="name" value="MyBean"/> </bean>для каждого метод
setProperty(value)будет вызываться.этот способ особенно полезен, если вам нужно более одного Боба на основе одной реализации.
например, если мы определим еще один боб в xml:
<bean id="Bean2" class="org.some.beans.MyBean"> <property name="id" value="2"/> <property name="name" value="EnotherBean"/> </bean>потом код это:
MyBean b1 = appContext.getBean("Bean1"); System.out.println("Bean id = " + b1.getId() + " name = " + b1.getName()); MyBean b2 = appContext.getBean("Bean2"); System.out.println("Bean id = " + b2.getId() + " name = " + b2.getName());печати
Bean id = 1 name = MyBean Bean id = 2 name = AnotherBeanтак, в вашем случае это должно выглядеть так:
@Repository("personDao") public class PersonDaoImpl extends AbstractDaoImpl implements PersonDao { Long maxResults; public void setMaxResults(Long maxResults) { this.maxResults = maxResults; } // Now use maxResults value in your code, it will be injected on Bean creation public void someMethod(Long results) { if (results < maxResults) { ... } } }
используйте класс Spring "PropertyPlaceholderConfigurer"
простой пример, показывающий файл свойств, считываемый динамически как свойство bean
<bean id="placeholderConfig" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="locations"> <list> <value>/WEB-INF/classes/config_properties/dev/database.properties</value> </list> </property> </bean> <bean id="devDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> <property name="driverClass" value="${dev.app.jdbc.driver}"/> <property name="jdbcUrl" value="${dev.app.jdbc.url}"/> <property name="user" value="${dev.app.jdbc.username}"/> <property name="password" value="${dev.app.jdbc.password}"/> <property name="acquireIncrement" value="3"/> <property name="minPoolSize" value="5"/> <property name="maxPoolSize" value="10"/> <property name="maxStatementsPerConnection" value="11000"/> <property name="numHelperThreads" value="8"/> <property name="idleConnectionTestPeriod" value="300"/> <property name="preferredTestQuery" value="SELECT 0"/> </bean>Свойства Файла
dev.приложение.интерфейс jdbc.драйвер=com.mysql.интерфейс jdbc.Водитель
dev.приложение.интерфейс jdbc.url=jdbc: mysql: / / localhost: 3306 / addvertisement
dev.приложение.интерфейс jdbc.username=root
dev.приложение.интерфейс jdbc.пароль=root
Comments