주석을 사용하여 구성된 Spring Bean에 속성 값을 삽입하는 방법은 무엇입니까? Spring XML 파일에 포함되어 있지

주석을 통해 클래스 패스에서 가져온 스프링 콩이 있습니다.

@Repository("personDao")
public class PersonDaoImpl extends AbstractDaoImpl implements PersonDao {
    // Implementation omitted
}

Spring XML 파일에는 PropertyPlaceholderConfigurer가 정의되어 있습니다.

<bean id="propertyConfigurer"
  class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="location" value="/WEB-INF/app.properties" />
</bean> 

app.properites의 속성 중 하나를 위에 표시된 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.



답변

EL 지원을 사용하여 Spring 3 에서이 작업을 수행 할 수 있습니다. 예:

@Value("#{systemProperties.databaseName}")
public void setDatabaseName(String dbName) { ... }

@Value("#{strategyBean.databaseKeyGenerator}")
public void setKeyGenerator(KeyGenerator kg) { ... }

systemProperties내재 된 오브젝트이며 strategyBeanBean 이름입니다.

Properties객체 에서 속성을 가져 오려고 할 때 작동하는 또 하나의 예 입니다. 또한 @Value필드에 적용 할 수 있음을 보여줍니다 .

@Value("#{myProperties['github.oauth.clientId']}")
private String githubOauthClientId;

여기입니다 블로그 게시물 내가 좀 더 정보를 원하시면 이것에 대해 썼다는.


답변

개인적으로 나는 문서 에서 봄 3.0의 새로운 방법을 좋아합니다 .

private @Value("${propertyName}") String propertyField;

게터 나 세터가 없습니다!

구성을 통해 속성을로드하는 경우 :

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
      p:location="classpath:propertyFile.properties" name="propertiesBean"/>

내 기쁨을 더하기 위해 IntelliJ에서 EL 표현식을 클릭하여 제어 할 수 있으며 속성 정의가 나타납니다!

완전히 비 XML 버전도 있습니다 .

@PropertySource("classpath:propertyFile.properties")
public class AppConfig {

    @Bean
    public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
        return new PropertySourcesPlaceholderConfigurer();
    }


답변

새로운 주석이 @Value봄 3.0.0M3은 . 표현뿐만 아니라 자리 표시 자도 @Value지원#{...}${...}


답변

<context:property-placeholder ... /> PropertyPlaceholderConfigurer와 동등한 XML입니다.

예 : applicationContext.xml

<context:property-placeholder location="classpath:test.properties"/>  

컴포넌트 클래스

 private @Value("${propertyName}") String propertyField;


답변

다른 대안은 아래에 표시된 appProperties Bean을 추가하는 것입니다.

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

검색 할 때이 Bean을 java.util.Propertiesresults.max 에서 값을 읽는 이름 이 지정된 특성을 포함하는app.properties . 이 Bean은 @Resource 어노테이션을 통해 모든 클래스에 java.util.Properties의 인스턴스로 종속성을 주입 할 수 있습니다.

개인적으로 appProperties에 의해 노출되는 속성을 정확하게 제한하고 app.properties를 두 번 읽을 필요가 없으므로이 솔루션을 제안합니다 (다른 제안보다).


답변

프로덕션 용 파일과 개발 용 재정의 파일 (배포되지 않음)의 두 가지 속성 파일이 필요합니다.

자동 배선 할 수있는 Properties Bean과 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>

PropertyConfigurer에서 특성 Bean을 참조하십시오.

<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="properties" ref="appProperties" />
</bean>


답변

주석 3을 사용하여 빈에 속성 상수를 직접 주입 할 수있는 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 "";
}

PropertyAnnotationAndPlaceholderConfigurer는 다음과 같습니다.

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);
                    }
                }
            }
        }
    }

}

취향에 따라 자유롭게 수정하십시오