我正在使用context:property-placeholder. 我如何以编程方式访问它们(@Value不起作用 - 我在开发时不知道财产所有权)?
主要问题是我无法更改applicationContext.xml文件,因为它是由“父”框架设置的
附言。这很奇怪,但又Environment.getProperty回来了null
我正在使用context:property-placeholder. 我如何以编程方式访问它们(@Value不起作用 - 我在开发时不知道财产所有权)?
主要问题是我无法更改applicationContext.xml文件,因为它是由“父”框架设置的
附言。这很奇怪,但又Environment.getProperty回来了null
不,你不能。PropertyPlaceholderConfigurer是 a BeanFactoryPostProcessor,它仅在 bean 创建期间“活着”。当它遇到一个${property}符号时,它会尝试根据其内部属性来解决它,但它不会使这些属性对容器可用。
也就是说:类似的问题一次又一次地出现,建议的解决方案通常是子类PropertyPlaceHolderConfigurer化并手动使属性可用于上下文。或使用PropertiesFactoryBean
我们使用以下方法来访问我们的应用程序的属性
<util:properties id="appProperties" location="classpath:app-config.properties" />
<context:property-placeholder properties-ref="appProperties"/>
然后,您可以使用限定符将属性自动装配到 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");
    }
}
如果您有更复杂的属性,您仍然可以使用 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"/>
    @Value
注释适用于 Spring 的新版本(在 v3.2.2 上测试)它是如何完成的:
在 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" />
在(根)您的源文件夹中创建 app-config.properties
my.property=test
my.property2=test2
创建控制器类
@Controller
public class XRDSBuilder
{
    @Value("${my.property}")
    private String myProperty;
    public String getMyProperty() { return myProperty; }
}
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;
    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; 
    } 
}
    在以下站点找到答案:
<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>
    <util:properties id="prop" location="location of prop file" />
这返回 java.util.Properties 对象
在 JAVA 代码中
Properties prop = (Properties) context.getBean("prop");
现在您可以访问,
prop.getProperty("key");
    如果您需要扫描多个位置的属性,则此方法有效...
<bean id="yourProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
    <property name="locations">
        <array value-type="org.springframework.core.io.Resource">
            <value>classpath:yourProperties.properties</value>
            <value>file:../conf/yourProperties.properties</value>
            <value>file:conf/yourProperties.properties</value>
            <value>file:yourProperties.properties</value>
        </array>
    </property>
    <property name="ignoreResourceNotFound" value="true" />
</bean>
<context:property-placeholder properties-ref="yourProperties" ignore-unresolvable="true"/>
然后在你的实际课程中......
@Autowired
Properties yourProperties;
使用 Spring 5.1.4 测试
在将它们放入属性占位符之前为您的属性创建 bean,以使属性易于在代码中访问。
前任:
<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")
假设您在该“父”框架中定义的属性文件
<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;