以编程方式访问property-placeholder创建的属性

fed*_*lov 40 spring properties

我正在阅读属性文件context:property-placeholder.如何以编程方式访问它们(@Value不起作用 - 我不知道开发时的属性标题)?

主要问题是我无法更改applicationContext.xml文件,因为它是由"父"框架设置的

PS.这很奇怪,但Environment.getProperty回归null

Sea*_*oyd 35

不,你不能.PropertyPlaceholderConfigurer是a BeanFactoryPostProcessor,它只是在bean创建过程中"活着".当遇到${property}符号时,它会尝试针对其内部属性解决该问题,但它不会使这些属性对容器可用.

也就是说:类似的问题一再出现,建议的解决方案通常是子类化PropertyPlaceHolderConfigurer并使属性可用于上下文.或者使用PropertiesFactoryBean


vah*_*apt 9

@Value
Run Code Online (Sandbox Code Playgroud)

注释适用于Spring的新版本(在v3.2.2上测试)以下是它的完成方式:

  1. 在spring配置文件中映射属性文件

    <!--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" />
    
    Run Code Online (Sandbox Code Playgroud)
  2. 在源文件夹内创建app-config.properties(root)

    my.property=test
    my.property2=test2
    
    Run Code Online (Sandbox Code Playgroud)
  3. 创建一个控制器类

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

Spring会自动将my.property的内容映射到控制器内的变量

映射到列表

适当的价值:

my.list.property=test,test2,test3
Run Code Online (Sandbox Code Playgroud)

控制器类配置:

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

高级映射

@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);
    }
}
Run Code Online (Sandbox Code Playgroud)

适当的价值:

my.complex.property=test1:value1,test2:value2
Run Code Online (Sandbox Code Playgroud)

控制器类:

@Value("#{PropertySplitter.map('${my.complex.property}')}")
Map<String, String> myComplexProperty;
Run Code Online (Sandbox Code Playgroud)

  • 这并没有回答所述的问题. (3认同)

小智 8

我们使用以下方法来访问应用程序的属性

<util:properties id="appProperties" location="classpath:app-config.properties" />
<context:property-placeholder properties-ref="appProperties"/>
Run Code Online (Sandbox Code Playgroud)

然后,您可以使用限定符将bean自动装配到bean中.

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

}
Run Code Online (Sandbox Code Playgroud)

如果您有更复杂的属性,您仍然可以使用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"/>
Run Code Online (Sandbox Code Playgroud)


Mac*_*las 5

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; 
    } 
}
Run Code Online (Sandbox Code Playgroud)


归档时间:

查看次数:

64170 次

最近记录:

6 年,7 月 前