spring 使用 @PropertySource 注释时未解析 @Value。如何配置 PropertySourcesPlaceholderConfigurer?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13728000/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 05:34:33  来源:igfitidea点击:

@Value not resolved when using @PropertySource annotation. How to configure PropertySourcesPlaceholderConfigurer?

springconfiguration

提问by matus

I have following configuration class:

我有以下配置类:

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

and I have service with property:

我有物业服务:

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

I receive error when I want to test the AppConfig configuration class with

当我想测试 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' 

The issue is documented in SPR-8539

该问题记录在 SPR-8539 中

but anyway I cannot figure out how to configure PropertySourcesPlaceholderConfigurerto get it work.

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

Edit 1

编辑 1

This approach works well with xml configuration

这种方法适用于 xml 配置

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

but I want to use java for configuration.

但我想使用 java 进行配置。

采纳答案by laffuste

If you use @PropertySource, properties have to be retrieved with:

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

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

If you want to retrieve with @Value("${mail.subject}"), you have to register the prop placeholder by xml.

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

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

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

回答by baybora.oren

as @cwash said;

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

}

回答by Sachchidanand Singh

I found the reason @valuewas not working for me is, @valuerequires PropertySourcesPlaceholderConfigurerinstead of a PropertyPlaceholderConfigurer. I did the same changes and it worked for me, I am using spring 4.0.3 release. I configured this using below code in my configuration file.

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

@Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
   return new PropertySourcesPlaceholderConfigurer();
}

回答by cwash

Don't you need a method on your @Configuration class that returns PropertySourcesPlaceholderConfigurer, annotated @Bean and is static, to register any @PropertySource with Spring?

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

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

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

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

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

回答by dimitrisli

I had the very same problem. @PropertySourceis not playing well with @Value. A quick workaround is to have an XML configuration which you'll refer to it from your Spring Java Configuration using @ImportResourceas usual and that XML configuration file will include a single entry: <context:property-placeholder />(of course with the needed namespace ceremony). Without any other change @Valuewill inject properties in your @Configurationpojo.

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

回答by Gowtham

This can also be configured in java this way

这也可以在java中这样配置

@Bean
public static PropertySourcesPlaceholderConfigurer properties() {
    PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer();
    configurer.setIgnoreUnresolvablePlaceholders(true);
    configurer.setIgnoreResourceNotFound(true);
    return configurer;
}

回答by NimChimpsky

That looks mighty complicated, can't you just do

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

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

then in code reference:

然后在代码参考中:

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

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

where some.properties looks something like this

some.properties 看起来像这样

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

For java based config you can do this

对于基于 Java 的配置,您可以执行此操作

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

And then just inject using @valueas before

然后@value像以前一样注入使用

回答by Artem Shitov

The thing is: as far as I get it, <util:propertes id="id" location="loc"/>, is just a shorthand for

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

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

(see documentation of util:properties). Thus, when you use util:properties, a standalone bean is created.

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

@PropertySource, on the other hand, as documentation says is an

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

annotation providing a convenient and declarative mechanism for adding a PropertySource to Spring's Environment'.

注释为将 PropertySource 添加到 Spring 的环境提供了一种方便的声明机制。

(see @PropertySource doc). So it doesn't create any bean.

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

Then "#{a['something']}" is a SpEL expression (see SpEL), that means "get something from bean'a'". When util:properties is used, the bean exists and the expression is meaningful, but when @PropertySource is used, there is no actual bean and the expression is meaningless.

然后 "#{a['something']}" 是一个 SpEL 表达式(参见SpEL),这意味着“从bean'a' 中获取一些东西”。当使用 util:properties 时,bean 存在并且表达式是有意义的,但是当使用 @PropertySource 时,没有实际的 bean 并且表达式没有意义。

You can workaround this either by using XML (which is the best way, I think) or by issuing a PropertiesFactoryBean by yourself, declaring it as a normal @Bean.

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

回答by Jan Bodnar

Since Spring 4.3 RC2 using PropertySourcesPlaceholderConfigureror <context:property-placeholder>is not needed anymore. We can use directly @PropertySourcewith @Value. See this Spring framework ticket

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

I have created a test application with Spring 5.1.3.RELEASE. The application.propertiescontains two pairs:

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

app.name=My application
app.version=1.1

The AppConfigloads the properties via @PropertySource.

通过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 {

}

The Applicationinjects the properties via @Valueand uses them.

通过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);
    }
}

The output is:

输出是:

$ 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

回答by Smart Coder

In my case, depends-on="bean1" was within property-placeholder was causing the issue. I removed that dependency and used @PostConstruct to achieve the same original functionality and was able to read the new values too.

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