67

我有以下配置类:

@Configuration
@PropertySource(name = "props", value = "classpath:/app-config.properties")
@ComponentScan("service")
public class AppConfig {

我有财产服务:

@Component 
public class SomeService {
    @Value("#{props['some.property']}") private String someProperty;

当我想测试 AppConfig 配置类时收到错误

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'someService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private java.lang.String service.SomeService.someProperty; nested exception is org.springframework.beans.factory.BeanExpressionException: Expression parsing failed; nested exception is org.springframework.expression.spel.SpelEvaluationException: EL1008E:(pos 0): Field or property 'props' cannot be found on object of type 'org.springframework.beans.factory.config.BeanExpressionContext' 

该问题记录在 SPR-8539 中

但无论如何我无法弄清楚如何配置PropertySourcesPlaceholderConfigurer 以使其工作。

编辑 1

这种方法适用于 xml 配置

<util:properties id="props" location="classpath:/app-config.properties" />

但我想使用java进行配置。

4

12 回答 12

136

正如@cwash 所说;

@Configuration
@PropertySource("classpath:/test-config.properties")
public class TestConfig {

     @Value("${name}")
     public String name;


     //You need this
     @Bean
     public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
        return new PropertySourcesPlaceholderConfigurer();
     }

}
于 2013-09-12T07:41:03.877 回答
35

如果您使用@PropertySource,则必须通过以下方式检索属性:

@Autowired
Environment env;
// ...
String subject = env.getProperty("mail.subject");

如果要使用 检索@Value("${mail.subject}"),则必须通过 xml 注册 prop 占位符。

原因: https ://jira.springsource.org/browse/SPR-8539

于 2013-03-22T03:38:32.797 回答
16

我发现@value对我不起作用的原因是,@value需要PropertySourcesPlaceholderConfigurer而不是PropertyPlaceholderConfigurer. 我做了同样的改变,它对我有用,我使用的是 spring 4.0.3 版本。我在我的配置文件中使用以下代码进行了配置。

@Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
   return new PropertySourcesPlaceholderConfigurer();
}
于 2014-11-27T06:56:35.963 回答
12

您是否不需要 @Configuration 类上的方法,该方法返回 PropertySourcesPlaceholderConfigurer、带注释的 @Bean 并且是静态的,以便向 Spring 注册任何 @PropertySource?

http://www.baeldung.com/2012/02/06/properties-with-spring/#java

https://jira.springsource.org/browse/SPR-8539

于 2013-06-10T19:21:59.407 回答
6

我有同样的问题。@PropertySource玩得不好@Value。一个快速的解决方法是拥有一个 XML 配置,您可以@ImportResource像往常一样使用 Spring Java 配置来引用它,并且该 XML 配置文件将包含一个条目:(<context:property-placeholder />当然还有所需的命名空间仪式)。没有任何其他更改将在您的pojo@Value中注入属性。@Configuration

于 2013-05-27T12:14:20.957 回答
5

这个在java中也可以这样配置

@Bean
public static PropertySourcesPlaceholderConfigurer properties() {
    PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer();
    configurer.setIgnoreUnresolvablePlaceholders(true);
    configurer.setIgnoreResourceNotFound(true);
    return configurer;
}
于 2016-04-21T20:17:08.607 回答
4

这看起来很复杂,你不能做吗

 <context:property-placeholder location="classpath:some.properties" ignore-unresolvable="true"/>

然后在代码参考中:

@Value("${myProperty}")
private String myString;

@Value("${myProperty.two}")
private String myStringTwo;

其中 some.properties 看起来像这样

myProperty = whatever
myProperty.two = something else\
that consists of multiline string

对于基于 java 的配置,您可以这样做

@Configuration
@PropertySource(value="classpath:some.properties")
public class SomeService {

@value然后像以前一样注入

于 2012-12-05T16:55:25.540 回答
2

问题是:据我所知,<util:propertes id="id" location="loc"/> 只是

<bean id="id" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
  <property name="location" value="loc"/>
</bean>

(请参阅util:properties 的文档)。因此,当您使用 util:properties 时,会创建一个独立的 bean。

另一方面,@PropertySource 正如文档所说的那样

注释提供了一种方便的声明性机制,用于将 PropertySource 添加到 Spring 的环境中。

(请参阅@PropertySource 文档)。所以它不会创建任何bean。

那么“#{a['something']}”是一个SpEL表达式(参见SpEL),意思是“从bean'a'中获取一些东西。使用 util:properties 时,bean 存在,表达式有意义,但使用 @PropertySource 时,没有实际的 bean,表达式无意义。

您可以通过使用 XML(我认为这是最好的方法)或自己发出 PropertiesFactoryBean 来解决此问题,将其声明为普通的 @Bean。

于 2013-05-31T09:40:55.880 回答
2

由于 Spring 4.3 RC2不再需要使用PropertySourcesPlaceholderConfigureror 。<context:property-placeholder>我们可以直接使用@PropertySourcewith @Value。请参阅此Spring 框架票证

我用 Spring 5.1.3.RELEASE 创建了一个测试应用程序。application.properties包含两对:

app.name=My application
app.version=1.1

通过AppConfig加载属性@PropertySource

package com.zetcode.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

@Configuration
@PropertySource(value = "application.properties", ignoreResourceNotFound = true)
public class AppConfig {

}

Application注入属性并使用@Value它们。

package com.zetcode;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;

@ComponentScan(basePackages = "com.zetcode")
public class Application {

    private static final Logger logger = LoggerFactory.getLogger(Application.class);

    @Value("${app.name}")
    private String appName;

    @Value("${app.version}")
    private String appVersion;

    public static void main(String[] args) {

        var ctx = new AnnotationConfigApplicationContext(Application.class);
        var app = ctx.getBean(Application.class);

        app.run();

        ctx.close();
    }

    public void run() {

        logger.info("Application name: {}", appName);
        logger.info("Application version: {}", appVersion);
    }
}

输出是:

$ mvn -q exec:java
22:20:10.894 [com.zetcode.Application.main()] INFO  com.zetcode.Application - Application name: My application
22:20:10.894 [com.zetcode.Application.main()] INFO  com.zetcode.Application - Application version: 1.1
于 2018-12-30T21:22:11.483 回答
0

在我的情况下,depends-on="bean1" 在属性占位符内导致了问题。我删除了该依赖项并使用 @PostConstruct 来实现相同的原始功能,并且也能够读取新值。

于 2020-02-25T15:21:19.097 回答
0

可能发生的另一件事:确保您的 @Value 注释值不是静态的。

于 2018-03-10T20:09:14.253 回答
0

如果是用xml配置,添加后

<context:property-placeholder location="..."/>

确保您的注释已激活。在我的情况下,由于这个原因没有获取属性:

<context:annotation-config/>

于 2021-08-21T14:50:39.893 回答