2012-07-10 43 views
30

Tôi đang đọc tệp thuộc tính sử dụng context:property-placeholder. Làm cách nào để truy cập chúng lập trình (@Value không hoạt động - Tôi không biết tiêu đề bất động sản tại thời điểm phát triển)?Truy cập có lập trình vào các thuộc tính được tạo bởi trình giữ chỗ thuộc tính

Vấn đề chính là tôi không thể thay đổi applicationContext.xml tập tin vì nó setted lên bởi "cha mẹ" khuôn khổ

ps. Thật lạ lùng nhưng Environment.getProperty trả về null

+0

Xem http: // stackoverflow.com/questions/5172392/how-to-programmatically-resolve-property-placeholder-in-spring. Có vẻ như có thể kể từ mùa xuân 3. – Vadzim

Trả lời

28

Không, bạn không thể. PropertyPlaceholderConfigurer là một BeanFactoryPostProcessor, nó chỉ là "còn sống" trong quá trình tạo hạt. Khi nó gặp một ký hiệu ${property}, nó cố gắng giải quyết điều đó so với các thuộc tính bên trong của nó, nhưng nó không làm cho các thuộc tính này có sẵn cho vùng chứa.

Điều đó cho biết: các câu hỏi tương tự đã xuất hiện lặp đi lặp lại, giải pháp được đề xuất thường là to subclass PropertyPlaceHolderConfigurer và làm cho Thuộc tính có sẵn theo ngữ cảnh theo cách thủ công. Hoặc use a PropertiesFactoryBean

4

Mùa xuân sau Đảo ngược phương pháp kiểm soát, điều này có nghĩa là chúng ta có thể chỉ cần tiêm thuộc tính cụ thể vào POJO. Nhưng có một số trường hợp, khi bạn muốn truy cập thuộc tính được đặt tên trực tiếp từ mã của bạn - một số có thể thấy nó là chống mẫu - điều này có thể đúng, nhưng hãy tập trung vào cách thực hiện.

PropertiesAccessor bên dưới cung cấp quyền truy cập vào các thuộc tính được tải bởi Property Placeholder và đóng gói các công cụ cụ thể của vùng chứa. Nó cũng lưu trữ các thuộc tính tìm thấy bởi vì cuộc gọi trên AbstractBeanFactory#resolveEmbeddedValue(String) không phải là giá rẻ.

@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; 
    } 
} 
9
@Value 

chú thích hoạt động trên phiên bản mới của mùa xuân (thử nghiệm trên v3.2.2) Sau đây là cách nó được thực hiện:

  1. Bản đồ đệ tài sản của bạn trong tập tin cấu hình mùa xuân

    <!--Import Info: 
    xmlns:context="http://www.springframework.org/schema/context" 
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context-3.2.xsd--> 
    
    <context:property-placeholder location="classpath:/app-config.properties" /> 
    
  2. Tạo app-config.properties bên trong (gốc) thư mục nguồn của bạn

    my.property=test 
    my.property2=test2 
    
  3. Tạo một lớp điều khiển

    @Controller 
    public class XRDSBuilder 
    { 
        @Value("${my.property}") 
        private String myProperty; 
    
        public String getMyProperty() { return myProperty; } 
    } 
    

mùa xuân sẽ tự động lập bản đồ các nội dung của tôi.tài sản để biến bạn bên trong bộ điều khiển

Mapping to a list

giá trị tài sản:

my.list.property=test,test2,test3 

điều khiển lớp cấu hình:

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

Advanced mapping

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

giá trị tài sản:

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

điều khiển lớp:

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

Điều này không trả lời câu hỏi như đã nêu. – Joel

+0

Câu trả lời hoàn hảo :) – Manoj

+0

Có phải là làm việc với thời gian chạy Mule ESB 3.7.3 không? Tôi không thể đạt được một giải pháp với điều đó, nó mang lại cho tôi một lỗi như 'Không thể chuyển đổi giá trị thuộc tính của loại' java.util.ArrayList 'thành loại yêu cầu' java.util.List 'cho thuộc tính' messageProcessors'' – Hayra

2

Tìm thấy câu trả lời ở bên dưới trang web:

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

Chúng tôi sử dụng các phương pháp sau đây để tính truy cập cho chúng tôi ứng dụng

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

Sau đó, bạn có sự sang trọng của các thuộc tính chỉ autowiring thành hạt bằng cách sử dụng vòng loại.

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

} 

Nếu bạn có nhiều thuộc tính phức tạp hơn, bạn vẫn có thể sử dụng tài nguyên không tìm thấy và bỏ qua không thể giải quyết. Chúng tôi sử dụng phương pháp này để ngoại giao một số cài đặt ứng dụng của chúng tôi.

<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"/> 
-1

Hãy asume mà bạn các thuộc tính tập tin được định nghĩa trong đó khuôn khổ "mẹ"

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

Bạn có thể sử dụng chú thích @value theo cách này:

@Value(value = "#{applicationProperties['my.app.property']}") 
private String myProperty; 
+0

Lỗi này phải đối mặt với lỗi trong Mùa xuân 4: Lập chỉ mục thành loại 'org.springframework.beans.factory.config.PropertyPlaceholderConfigurer' không được hỗ trợ –

+0

Giống như @SeanPatrickFloyd đã nhận xét: "câu hỏi _similar đã xuất hiện lại và một lần nữa, giải pháp được đề xuất thường là phân lớp PropertyPlaceHolderConfigurer và làm cho Thuộc tính có sẵn theo ngữ cảnh một cách thủ công. Hoặc sử dụng ** PropertiesFactoryBean ** _. " Tôi hy vọng điều này sẽ giúp bạn: [Đọc-giá-từ-thuộc tính-tệp-tại-Thời gian chạy] (https://stackoverflow.com/questions/5665296/reading-valued-from-properties-file-at-runtime/5673678# 5673678) –

Các vấn đề liên quan