Access properties file programmatically with Spring?

前端 未结 15 1676
说谎
说谎 2020-11-27 09:37

We use the code below to inject Spring beans with properties from a properties file.



        
15条回答
  •  孤独总比滥情好
    2020-11-27 09:37

    If all you want to do is access placeholder value from code, there is the @Value annotation:

    @Value("${settings.some.property}")
    String someValue;
    

    To access placeholders From SPEL use this syntax:

    #('${settings.some.property}')
    

    To expose configuration to views that have SPEL turned off, one can use this trick:

    package com.my.app;
    
    import java.util.Collection;
    import java.util.Map;
    import java.util.Set;
    
    import org.springframework.beans.factory.BeanFactory;
    import org.springframework.beans.factory.BeanFactoryAware;
    import org.springframework.beans.factory.config.ConfigurableBeanFactory;
    import org.springframework.stereotype.Component;
    
    @Component
    public class PropertyPlaceholderExposer implements Map, BeanFactoryAware {  
        ConfigurableBeanFactory beanFactory; 
    
        @Override
        public void setBeanFactory(BeanFactory beanFactory) {
            this.beanFactory = (ConfigurableBeanFactory) beanFactory;
        }
    
        protected String resolveProperty(String name) {
            String rv = beanFactory.resolveEmbeddedValue("${" + name + "}");
    
            return rv;
        }
    
        @Override
        public String get(Object key) {
            return resolveProperty(key.toString());
        }
    
        @Override
        public boolean containsKey(Object key) {
            try {
                resolveProperty(key.toString());
                return true;
            }
            catch(Exception e) {
                return false;
            }
        }
    
        @Override public boolean isEmpty() { return false; }
        @Override public Set keySet() { throw new UnsupportedOperationException(); }
        @Override public Set> entrySet() { throw new UnsupportedOperationException(); }
        @Override public Collection values() { throw new UnsupportedOperationException(); }
        @Override public int size() { throw new UnsupportedOperationException(); }
        @Override public boolean containsValue(Object value) { throw new UnsupportedOperationException(); }
        @Override public void clear() { throw new UnsupportedOperationException(); }
        @Override public String put(String key, String value) { throw new UnsupportedOperationException(); }
        @Override public String remove(Object key) { throw new UnsupportedOperationException(); }
        @Override public void putAll(Map t) { throw new UnsupportedOperationException(); }
    }
    

    And then use the exposer to expose properties to a view:

    
        
        
            
                
                    
                
            
        
    
    

    Then in view, use the exposed properties like this:

    ${config['settings.some.property']}
    

    This solution has the advantage that you can rely on standard placeholder implementation injected by the context:property-placeholder tag.

    Now as a final note, if you really need a to capture all placeholder properties and their values, you have to pipe them through StringValueResolver to make sure that placeholders work inside the property values as expected. The following code will do that.

    package com.my.app;
    
    import java.util.Collection;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Properties;
    import java.util.Set;
    
    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
    import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
    import org.springframework.util.StringValueResolver;
    
    public class AppConfig extends PropertyPlaceholderConfigurer implements Map {
    
        Map props = new HashMap();
    
        @Override
        protected void processProperties(ConfigurableListableBeanFactory beanFactory, Properties props)
                throws BeansException {
    
            this.props.clear();
            for (Entry e: props.entrySet())
                this.props.put(e.getKey().toString(), e.getValue().toString());
    
            super.processProperties(beanFactory, props);
        }
    
        @Override
        protected void doProcessProperties(ConfigurableListableBeanFactory beanFactoryToProcess,
                StringValueResolver valueResolver) {
    
            super.doProcessProperties(beanFactoryToProcess, valueResolver);
    
            for(Entry e: props.entrySet())
                e.setValue(valueResolver.resolveStringValue(e.getValue()));
        }
    
        // Implement map interface to access stored properties
        @Override public Set keySet() { return props.keySet(); }
        @Override public Set> entrySet() { return props.entrySet(); }
        @Override public Collection values() { return props.values(); }
        @Override public int size() { return props.size(); }
        @Override public boolean isEmpty() { return props.isEmpty(); }
        @Override public boolean containsValue(Object value) { return props.containsValue(value); }
        @Override public boolean containsKey(Object key) { return props.containsKey(key); }
        @Override public String get(Object key) { return props.get(key); }
        @Override public void clear() { throw new UnsupportedOperationException(); }
        @Override public String put(String key, String value) { throw new UnsupportedOperationException(); }
        @Override public String remove(Object key) { throw new UnsupportedOperationException(); }
        @Override public void putAll(Map t) { throw new UnsupportedOperationException(); }
    }
    

提交回复
热议问题