【问题标题】:@Value not resolved when using @PropertySource annotation. How to configure PropertySourcesPlaceholderConfigurer?使用 @PropertySource 注释时未解析 @Value。如何配置 PropertySourcesPlaceholderConfigurer?
【发布时间】:2012-11-23 13:26:48
【问题描述】:

我有以下配置类:

@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' 

问题记录在in SPR-8539

但无论如何我不知道如何配置 PropertySourcesPlaceholderConfigurer 以使其正常工作。

编辑 1

这种方法适用于 xml 配置

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

但我想使用java进行配置。

【问题讨论】:

  • 你能接受laffuste的回答吗?它有效。
  • 完成 :) 我没有进行更多调查,但提到勾选标记为“不会修复”

标签: spring configuration


【解决方案1】:

如果你是用xml配置,添加后

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

【讨论】:

    【解决方案2】:

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

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

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

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

    【讨论】:

    • 您还可以在 java 中添加静态 PropertySourcesPlaceholderConfigurer bean 以允许 @Value 工作。这是一个示例 public static PropertySourcesPlaceholderConfigurer properties() { PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer(); configurer.setIgnoreUnresolvablePlaceholders(true);配置器.setIgnoreResourceNotFound(true);返回配置器; }
    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

      从 Spring 4.3 RC2 开始,不再需要使用 PropertySourcesPlaceholderConfigurer&lt;context:property-placeholder&gt;。我们可以直接使用@PropertySource@Value。看到这个Spring framework ticket

      我使用 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
      

      【讨论】:

        【解决方案5】:

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

        【讨论】:

        • 这也是 java 文档中建议的方式。请参阅docs.spring.io/spring/docs/4.2.4.RELEASE/javadoc-api/org/…中的“使用@Value 注释”
        • 这很好用,我们不需要使用 xml 配置文件。只需 PropertySource 注解并用 Bean 注解声明 PropertySourcesPlaceholderConfigurer 就足够了。
        【解决方案6】:

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

        【讨论】:

          【解决方案7】:

          java中也可以这样配置

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

          【讨论】:

            【解决方案8】:

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

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

            【讨论】:

            • 我正在使用 Spring 4.3.10 并且“@value”正在使用“@PropertySource”。我没有配置 PropertySourcesPlaceholderConfigurer bean
            • 确认,Spring 4.3.10 不需要 PropertySourcesPlaceholderConfigurer。
            【解决方案9】:

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

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

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

            【讨论】:

              【解决方案10】:

              问题是:据我所知, 只是

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

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

              另一方面,正如文档所说,@PropertySource 是一个

              注解提供了一种方便的声明机制 将 PropertySource 添加到 Spring 的 Environment'。

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

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

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

              【讨论】:

                【解决方案11】:

                我遇到了同样的问题。 @PropertySource 不能很好地与 @Value 配合使用。一个快速的解决方法是拥有一个 XML 配置,您将像往常一样使用 @ImportResource 从 Spring Java 配置中引用它,并且该 XML 配置文件将包含一个条目:&lt;context:property-placeholder /&gt;(当然还有所需的命名空间仪式) .无需任何其他更改 @Value 将在您的 @Configuration pojo 中注入属性。

                【讨论】:

                  【解决方案12】:

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

                   <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 注入

                  【讨论】:

                  • 文本文件中没有属性:@PropertySource(name = "props", value = "classpath:/app-config.properties") 我只想用 Spring 3 中可用的 java config 替换 .xml
                  • 它不能解决我的问题。正如我所说,它适用于 spring xml 配置。但是我需要我写的带有值注释的 Java 配置解决方案。我不是在寻找替代解决方案。
                  • 我认为我不应该使用 @Configuration 来注释服务。我试图将 @PropertySource 直接移动到服务,但错误是一样的
                  • @coffy 我正在寻找完全相同的东西。你还记得解决这个问题的方法吗?
                  • @matus,不,它不能那样工作(Spring 4.3.1)。
                  猜你喜欢
                  • 2020-05-08
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2017-09-04
                  • 2016-05-21
                  相关资源
                  最近更新 更多