복붙노트

[SPRING] property-placeholder에 의해 생성 된 속성에 대한 프로그래밍 방식의 액세스

SPRING

property-placeholder에 의해 생성 된 속성에 대한 프로그래밍 방식의 액세스

컨텍스트를 사용하여 속성 파일을 읽었습니다 : property-placeholder. 프로그래밍 방식으로 액세스하려면 어떻게해야합니까 (@Value가 작동하지 않습니다 - 개발 중 속성 제목을 알지 못합니다)?

주요 문제는 "parent"프레임 워크에 의해 set up 되었기 때문에 applicationContext.xml 파일을 변경할 수 없다는 것입니다.

추신. 그것은 이상하지만 Environment.getProperty가 null을 반환합니다.

해결법

  1. ==============================

    1.아니, 할 수 없어. PropertyPlaceholderConfigurer는 BeanFactoryPostProcessor이며 빈 생성 중에 "살아있다". $ {property} 표기법을 발견하면 내부 속성에 대해이를 해결하려고하지만 컨테이너에서 이러한 속성을 사용할 수 없게 만듭니다.

    아니, 할 수 없어. PropertyPlaceholderConfigurer는 BeanFactoryPostProcessor이며 빈 생성 중에 "살아있다". $ {property} 표기법을 발견하면 내부 속성에 대해이를 해결하려고하지만 컨테이너에서 이러한 속성을 사용할 수 없게 만듭니다.

    즉, 비슷한 질문이 반복해서 등장합니다. 제안 된 솔루션은 대개 PropertyPlaceHolderConfigurer를 서브 클래스 화하고 속성을 컨텍스트에서 수동으로 사용할 수있게 만드는 것입니다. 또는 PropertiesFactoryBean을 사용하십시오.

  2. ==============================

    2.

    @Value
    

    주석은 Spring의 새 릴리스에서 작동합니다 (v3.2.2에서 테스트 됨). 다음과 같이 수행됩니다.

    Spring은 my.property의 내용을 컨트롤러 내부의 변수에 자동으로 매핑합니다.

    목록에 매핑

    재산 가치:

    my.list.property=test,test2,test3
    

    컨트롤러 클래스 구성 :

    @Value("#{'${my.list.property}'.split(',')}")
    private List<String> myListProperty;
    

    고급 매핑

    @Component("PropertySplitter")
    public class PropertySplitter {
    
        /**
         * Example: one.example.property = KEY1:VALUE1,KEY2:VALUE2
         */
        public Map<String, String> map(String property) {
            return this.map(property, ",");
        }
    
        /**
         * Example: one.example.property = KEY1:VALUE1.1,VALUE1.2;KEY2:VALUE2.1,VALUE2.2
         */
        public Map<String, List<String>> mapOfList(String property) {
            Map<String, String> map = this.map(property, ";");
    
            Map<String, List<String>> mapOfList = new HashMap<>();
            for (Entry<String, String> entry : map.entrySet()) {
                mapOfList.put(entry.getKey(), this.list(entry.getValue()));
            }
    
            return mapOfList;
        }
    
        /**
         * Example: one.example.property = VALUE1,VALUE2,VALUE3,VALUE4
         */
        public List<String> list(String property) {
            return this.list(property, ",");
        }
    
        /**
         * Example: one.example.property = VALUE1.1,VALUE1.2;VALUE2.1,VALUE2.2
         */
        public List<List<String>> groupedList(String property) {
            List<String> unGroupedList = this.list(property, ";");
    
            List<List<String>> groupedList = new ArrayList<>();
            for (String group : unGroupedList) {
                groupedList.add(this.list(group));
            }
    
            return groupedList;
    
        }
    
        private List<String> list(String property, String splitter) {
            return Splitter.on(splitter).omitEmptyStrings().trimResults().splitToList(property);
        }
    
        private Map<String, String> map(String property, String splitter) {
            return Splitter.on(splitter).omitEmptyStrings().trimResults().withKeyValueSeparator(":").split(property);
        }
    }
    

    재산 가치:

    my.complex.property=test1:value1,test2:value2
    

    컨트롤러 클래스 :

    @Value("#{PropertySplitter.map('${my.complex.property}')}")
    Map<String, String> myComplexProperty;
    
  3. ==============================

    3.우리는 다음 접근 방식을 사용하여 애플리케이션의 속성에 액세스합니다.

    우리는 다음 접근 방식을 사용하여 애플리케이션의 속성에 액세스합니다.

    <util:properties id="appProperties" location="classpath:app-config.properties" />
    <context:property-placeholder properties-ref="appProperties"/>
    

    그런 다음 한정자를 사용하여 빈에 속성을 autowiring하는 사치를 누릴 수 있습니다.

    @Component
    public class PropertyAccessBean {
    
        private Properties properties;
    
        @Autowired
        @Qualifier("appProperties")
        public void setProperties(Properties properties) {
            this.properties = properties;
        }
    
        public void doSomething() {
            String property = properties.getProperty("code.version");
        }
    
    }
    

    더 복잡한 속성이있는 경우 ignore-resource-not-found 및 ignore-unresolvable을 계속 사용할 수 있습니다. 우리는이 접근 방식을 사용하여 일부 응용 프로그램 설정을 외부화합니다.

     <util:properties id="appProperties" ignore-resource-not-found="true"
        location="classpath:build.properties,classpath:application.properties,
                                file:/data/override.properties"/>
     <context:property-placeholder ignore-unresolvable="true" properties-ref="appProperties"/>
    
  4. ==============================

    4.Spring은 Inversion Of Control 접근법을 따른다. 이것은 POJO에 특정 속성을 주입 할 수 있다는 것을 의미한다. 그러나 코드에서 직접 이름으로 지정된 속성에 액세스하려는 일부 경우가 있습니다. 일부는 패턴으로 볼 수 있습니다. 이는 명백한 사실이지만이를 수행하는 방법에 집중할 수 있습니다.

    Spring은 Inversion Of Control 접근법을 따른다. 이것은 POJO에 특정 속성을 주입 할 수 있다는 것을 의미한다. 그러나 코드에서 직접 이름으로 지정된 속성에 액세스하려는 일부 경우가 있습니다. 일부는 패턴으로 볼 수 있습니다. 이는 명백한 사실이지만이를 수행하는 방법에 집중할 수 있습니다.

    아래의 PropertiesAccessor는 Property Placeholder에 의해로드 된 속성에 대한 액세스를 제공하고 컨테이너 관련 항목을 캡슐화합니다. 또한 AbstractBeanFactory # resolveEmbeddedValue (String)에 대한 호출이 저렴하지 않기 때문에 발견 된 속성을 캐시합니다.

    @Named 
    public class PropertiesAccessor {
    
        private final AbstractBeanFactory beanFactory;
    
        private final Map<String,String> cache = new ConcurrentHashMap<>(); 
    
        @Inject 
        protected PropertiesAccessor(AbstractBeanFactory beanFactory) {
            this.beanFactory = beanFactory; 
        } 
    
        public  String getProperty(String key) { 
            if(cache.containsKey(key)){ 
                return cache.get(key); 
            } 
    
            String foundProp = null; 
            try { 
                foundProp = beanFactory.resolveEmbeddedValue("${" + key.trim() + "}");        
                cache.put(key,foundProp);        
            } catch (IllegalArgumentException ex) { 
               // ok - property was not found 
            } 
    
            return foundProp; 
        } 
    }
    
  5. ==============================

    5.아래 사이트에서 찾을 수있는 답변 :

    아래 사이트에서 찾을 수있는 답변 :

    http://forum.spring.io/forum/spring-projects/container/106180-programmatic-access-to-properties-defined-for-the-propertyplaceholderconfigurer

    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" id="propertyConfigurer">
    <property name="properties" ref="props" />
    </bean>
    <bean id="props" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
      <property name="location" value="file:C:/CONFIG/settings.properties"/>
    </bean>
    
  6. ==============================

    6.속성을 속성 자리 표시 자에 넣기 전에 속성에 대한 빈을 만들어 속성을 코드에 쉽게 액세스 할 수있게 만듭니다.

    속성을 속성 자리 표시 자에 넣기 전에 속성에 대한 빈을 만들어 속성을 코드에 쉽게 액세스 할 수있게 만듭니다.

    전의:

    <bean id="configProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
        <property name="resources" value="classpath:META-INF/spring/config.properties" />
    </bean>
    
    <context:property-placeholder properties-ref="configProperties" ignore-unresolvable="true"/>
    

    암호:

    @Autowired
    private PropertiesFactoryBean configProperties;
    

    @Resource (name = "configProperties")를 사용할 수도 있습니다.

  7. ==============================

    7.

    <util:properties id="prop" location="location of prop file" />
    

    이 java.util.Properties 객체를 반환합니다.

    자바 코드

    Properties prop = (Properties) context.getBean("prop");
    

    이제 당신은,

    prop.getProperty("key");
    
  8. ==============================

    8.그 "상위"프레임 워크에 정의 된 특성 파일

    그 "상위"프레임 워크에 정의 된 특성 파일

    <bean id="applicationProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
        <property name="location" value="classpath:main.properties" />
    </bean>
    

    이런 식으로 @Value 주석을 사용할 수 있습니다.

    @Value( value = "#{applicationProperties['my.app.property']}" )
    private String myProperty;
    
  9. from https://stackoverflow.com/questions/11415711/programmatic-access-to-properties-created-by-property-placeholder by cc-by-sa and MIT license