webentwicklung-frage-antwort-db.com.de

@Value nicht aufgelöst, wenn @PropertySource-Annotation verwendet wird. Wie konfiguriere ich PropertySourcesPlaceholderConfigurer?

Ich habe folgende Konfigurationsklasse:

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

und ich habe Dienst mit Eigentum:

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

Ich erhalte eine Fehlermeldung, wenn ich die AppConfig-Konfigurationsklasse mit testen möchte

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' 

Das Problem ist dokumentiert in SPR-8539

ich kann aber trotzdem nicht herausfinden, wie man PropertySourcesPlaceholderConfigurer konfiguriert, damit es funktioniert.

Bearbeiten 1

Dieser Ansatz funktioniert gut mit der XML-Konfiguration

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

aber ich möchte Java für die Konfiguration verwenden.

54
matus

Wenn Sie @PropertySource verwenden, müssen Eigenschaften abgerufen werden mit:

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

Wenn Sie mit @Value ("$ {mail.subject}") abrufen möchten, müssen Sie den Platzhalter für Requisiten mit xml registrieren.

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

30
laffuste

wie @cwash sagte;

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

}
119
baybora.oren

Ich fand heraus, dass @value für mich nicht funktioniert hat, @value erfordert PropertySourcesPlaceholderConfigurer anstelle eines PropertyPlaceholderConfigurer. Ich habe die gleichen Änderungen vorgenommen und es hat für mich funktioniert. Ich habe dies mit dem folgenden Code in meiner Konfigurationsdatei konfiguriert.

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

Benötigen Sie eine Methode in Ihrer @Configuration-Klasse, die PropertySourcesPlaceholderConfigurer zurückgibt, @Bean kommentiert und statisch ist, um @PropertySource bei Spring zu registrieren? 

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

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

11
cwash

Ich hatte das gleiche Problem. @PropertySource spielt nicht gut mit @Value. Eine schnelle Problemumgehung besteht darin, eine XML-Konfiguration zu haben, auf die Sie in Ihrer Spring Java-Konfiguration wie üblich mit @ImportResource verweisen. Diese XML-Konfigurationsdatei enthält einen einzigen Eintrag: <context:property-placeholder /> (natürlich mit der erforderlichen Namespace-Zeremonie). Ohne weitere Änderung wird @Value Eigenschaften in Ihren @Configuration-Pojo einfügen.

6
dimitrisli

Dies kann auch auf diese Weise in Java konfiguriert werden

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

Das sieht mächtig kompliziert aus, kannst du es nicht einfach tun 

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

dann in der Code-Referenz:

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

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

wo some.properties so aussieht

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

Für eine Java-basierte Konfiguration können Sie dies tun

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

Und dann einfach mit @value wie zuvor injizieren

3
NimChimpsky

Die Sache ist: Soweit ich es verstanden habe, ist <util: propertyes id = "id" location = "loc" /> nur eine Abkürzung für 

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

(siehe Dokumentation von util: properties ). Wenn Sie also util: properties verwenden, wird eine Standalone-Bean erstellt.

@PropertySource dagegen, wie die Dokumentation sagt, ist ein 

anmerkung, die einen bequemen und deklarativen Mechanismus für .__ bereitstellt. Hinzufügen einer PropertySource zur Spring-Umgebung '.

(Siehe @PropertySource doc ). So schafft es keine Bohne.

Dann ist "# {a ['etwas"]} "ein SpEL-Ausdruck (siehe SpEL ), dh" etwas von bean' a '"erhalten. Wenn util: properties verwendet wird, ist die Bean vorhanden und der Ausdruck ist von Bedeutung, aber wenn @PropertySource verwendet wird, gibt es keine tatsächliche Bean und der Ausdruck ist bedeutungslos.

Sie können dieses Problem umgehen, indem Sie entweder XML verwenden (was der beste Weg ist, denke ich) oder indem Sie selbst eine PropertiesFactoryBean ausgeben und sie als normale @Bean deklarieren.

2
Artem Shitov

Seit Spring 4.3 wird RC2 mit PropertySourcesPlaceholderConfigurer oder <context:property-placeholder> nicht mehr benötigt. Wir können @PropertySource direkt mit @Value verwenden. Sehen Sie diese Frühlings-Rahmenticket

Ich habe eine Testanwendung mit Spring 5.1.3.RELEASE ..__ erstellt. Der application.properties enthält zwei Paare:

app.name=My application
app.version=1.1

Die Variable AppConfig lädt die Eigenschaften über @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 {

}

Die Variable Application injiziert die Eigenschaften über @Value und verwendet sie.

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

Die Ausgabe ist:

$ 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
1
Jan Bodnar

Möglicherweise geschieht Folgendes: Stellen Sie sicher, dass Ihre mit Annotationen versehenen Werte für @Value nicht statisch sind.

0
davo