Как я могу ввести значение свойства в 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?

920   17  

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

    Ничего не найдено.