Der Wert für Spring Boot application.properties wird nicht ausgefüllt

90

Ich habe eine sehr einfache Spring Boot-App, mit der ich versuchen möchte, mit einer externen Konfiguration zu arbeiten. Ich habe versucht, den Informationen auf der zu folgen Federstiefeldokumentation aber ich stoße auf eine Straßensperre.

Wenn ich die App unterhalb der externen Konfiguration in der Datei application.properties ausführe, wird sie nicht in die Variable innerhalb der Bean eingefügt. Ich bin sicher, ich mache etwas Dummes, danke für alle Vorschläge.

MyBean.java (befindet sich in / src / main / java / foo / bar /)

package foo.bar;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.stereotype.Component;

@Component
public class MyBean {

    @Value("${some.prop}")
    private String prop;

    public MyBean() {
        System.out.println("================== " + prop + "================== ");
    }
}

Application.java (befindet sich in / src / main / java / foo /)

package foo;

import foo.bar.MyBean;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.SpringApplication;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan
@EnableAutoConfiguration
public class Application {

    @Autowired
    private MyBean myBean;

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

application.properties (befindet sich in / src / main / resources /)

some.prop=aabbcc

Protokollausgabe beim Ausführen der Spring Boot-App:

grb-macbook-pro:properties-test-app grahamrb$ java -jar ./build/libs/properties-test-app-0.1.0.jar

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v1.1.5.RELEASE)

2014-09-10 21:28:42.149  INFO 16554 --- [           main] foo.Application                          : Starting Application on grb-macbook-pro.local with PID 16554 (/Users/grahamrb/Dropbox/dev-projects/spring-apps/properties-test-app/build/libs/properties-test-app-0.1.0.jar started by grahamrb in /Users/grahamrb/Dropbox/dev-projects/spring-apps/properties-test-app)
2014-09-10 21:28:42.196  INFO 16554 --- [           main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@67e38ec8: startup date [Wed Sep 10 21:28:42 EST 2014]; root of context hierarchy
2014-09-10 21:28:42.828  INFO 16554 --- [           main] o.s.b.f.s.DefaultListableBeanFactory     : Overriding bean definition for bean 'beanNameViewResolver': replacing [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration$WhitelabelErrorViewConfiguration; factoryMethodName=beanNameViewResolver; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/ErrorMvcAutoConfiguration$WhitelabelErrorViewConfiguration.class]] with [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter; factoryMethodName=beanNameViewResolver; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter.class]]
2014-09-10 21:28:43.592  INFO 16554 --- [           main] .t.TomcatEmbeddedServletContainerFactory : Server initialized with port: 8080
2014-09-10 21:28:43.784  INFO 16554 --- [           main] o.apache.catalina.core.StandardService   : Starting service Tomcat
2014-09-10 21:28:43.785  INFO 16554 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet Engine: Apache Tomcat/7.0.54
2014-09-10 21:28:43.889  INFO 16554 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2014-09-10 21:28:43.889  INFO 16554 --- [ost-startStop-1] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 1695 ms
2014-09-10 21:28:44.391  INFO 16554 --- [ost-startStop-1] o.s.b.c.e.ServletRegistrationBean        : Mapping servlet: 'dispatcherServlet' to [/]
2014-09-10 21:28:44.393  INFO 16554 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean  : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
================== null==================
2014-09-10 21:28:44.606  INFO 16554 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2014-09-10 21:28:44.679  INFO 16554 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],methods=[],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)
2014-09-10 21:28:44.679  INFO 16554 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],methods=[],params=[],headers=[],consumes=[],produces=[text/html],custom=[]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest)
2014-09-10 21:28:44.716  INFO 16554 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2014-09-10 21:28:44.716  INFO 16554 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2014-09-10 21:28:44.902  INFO 16554 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
2014-09-10 21:28:44.963  INFO 16554 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080/http
2014-09-10 21:28:44.965  INFO 16554 --- [           main] foo.Application                          : Started Application in 3.316 seconds (JVM running for 3.822)
^C2014-09-10 21:28:54.223  INFO 16554 --- [       Thread-2] ationConfigEmbeddedWebApplicationContext : Closing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@67e38ec8: startup date [Wed Sep 10 21:28:42 EST 2014]; root of context hierarchy
2014-09-10 21:28:54.225  INFO 16554 --- [       Thread-2] o.s.j.e.a.AnnotationMBeanExporter        : Unregistering JMX-exposed beans on shutdown
Grahamrb
quelle
4
Und wie sollte @Valueersetzt werden, bevor eine Bohne gebaut wird? Ihre Art zu "erkennen", ob der Wert eingestellt ist, ist falsch. In diesem Moment ist es immer null, wie @Valuees nach der Objektkonstruktion verarbeitet wird.
M. Deinum

Antworten:

155

Die Art und Weise, wie Sie die Injection der Eigenschaft ausführen, funktioniert nicht, da die Injection nach dem Aufruf des Konstruktors erfolgt.

Sie müssen einen der folgenden Schritte ausführen:

Bessere Lösung

@Component
public class MyBean {

    private final String prop;

    @Autowired
    public MyBean(@Value("${some.prop}") String prop) {
        this.prop = prop;
        System.out.println("================== " + prop + "================== ");
    }
}

Lösung, die funktioniert, aber weniger testbar und etwas weniger lesbar ist

@Component
public class MyBean {

    @Value("${some.prop}")
    private String prop;

    public MyBean() {

    }

    @PostConstruct
    public void init() {
        System.out.println("================== " + prop + "================== ");
    }
}

Beachten Sie auch, dass dies nicht Spring Boot-spezifisch ist, sondern für jede Spring-Anwendung gilt

geoand
quelle
Ich musste dem Konstruktor eine @ Autowired-Annotation hinzufügen, damit es funktioniert
Sébastien Tromp
1
Danke für den Tipp. Dies sollte in der Spring-Dokumentation sein, in der es um die @ Value-Annotation geht - aber diese Leute scheinen nicht an Feedback zu ihrer Dokumentation interessiert zu sein :(
Alex Worden
1
Ersparte mir etwas Frsutration. Vielen Dank!
Robert Moskal
1
@geoand Was ist, wenn Sie mehr als 10 Werte haben, müssten Sie alle 10 so eingeben, wie Sie es getan haben? Oder gibt es einen saubereren Weg
Jesse
1
@Jackie In der Tat gibt es einen saubereren Weg! Check out @ConfigurationPropertiesund @EnableConfigurationPropertiesAnmerkungen
geoand
5

Der Benutzer "geoand" weist hier zu Recht auf die Gründe hin und gibt eine Lösung an. Ein besserer Ansatz besteht jedoch darin, Ihre Konfiguration in eine separate Klasse zu kapseln, z. B. die Java-Klasse SystemContiguration, und diese Klasse dann in die Dienste einzufügen, die Sie für diese Felder verwenden möchten.

Ihre derzeitige Methode (@grahamrb), Konfigurationswerte direkt in Dienste einzulesen, ist fehleranfällig und würde zu Refactoring-Kopfschmerzen führen, wenn der Name der Konfigurationseinstellung geändert wird.

Amit Kr
quelle
Wie würde es nicht weniger Kopfschmerzen geben, wenn Sie eine separate Klasse für diese Eigenschaft hätten? Sie haben noch eine Zeichenfolge, die beim Refactoring
berücksichtigt werden muss
4
Es gibt nur einen Ort, an den Sie sich "erinnern" müssen, nicht die N-Nummer. Die in SystemContiguration vorhandenen Skalarwerte geben Ihnen eine starke Typisierung. Wenn es eine Geschäftslogik gibt, die "Gabeln" hat ~~~ basierend auf Werten, die aus der Konfiguration stammen ~~~ ..... ist es besser, etwas in die Klasse / businessLogic einzufügen, die die Werte benötigt. Aka, es ist viel einfacher, sich über SystemContiguration lustig zu machen, als zu versuchen, @Value überall zum Laufen zu bringen.
GranadaCoder
2

Eigentlich funktioniert für mich unten gut.

@Component
public class MyBean {

   public static String prop;

   @Value("${some.prop}")
   public void setProp(String prop) {
      this.prop= prop;
   }

   public MyBean() {

   }

   @PostConstruct
   public void init() {
      System.out.println("================== " + prop + "================== ");
   }

}}

Wo immer ich will, rufe einfach an

MyBean.prop

es wird Wert zurückgeben.

Raj Mohamad
quelle
2

Diese Antwort kann auf Ihren Fall zutreffen oder auch nicht ... Nachdem ich ein ähnliches Symptom hatte und meinen Code viele Male überprüft habe und alles gut aussah, wurde die @ValueEinstellung immer noch nicht wirksam. Und dann, nachdem ich File > Invalidate Cache / Restartmit meiner IntelliJ(meiner IDE) fertig war, ging das Problem weg ...

Dies ist sehr einfach zu versuchen und kann einen Versuch wert sein

leeyuiwah
quelle
1

Mit der Environment-Klasse können wir eine Anwendung erhalten. Eigenschaftenwerte

@Autowired,

private Environment env;

und Zugriff mit

String password =env.getProperty(your property key);
ramakotireddy nagireddy
quelle
0

folge diesen Schritten. 1: - Erstellen Sie Ihre Konfigurationsklasse wie unten gezeigt

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.beans.factory.annotation.Value;

@Configuration
public class YourConfiguration{

    // passing the key which you set in application.properties
    @Value("${some.pro}")
    private String somePro;

   // getting the value from that key which you set in application.properties
    @Bean
    public String getsomePro() {
        return somePro;
    }
}

2: - Wenn Sie eine Konfigurationsklasse haben, fügen Sie die Variable aus einer Konfiguration ein, die Sie benötigen.

@Component
public class YourService {

    @Autowired
    private String getsomePro;

    // now you have a value in getsomePro variable automatically.
}
Fazle Subhan
quelle
0

Wenn Sie in einem großen Projekt mit mehreren Modulen und mehreren verschiedenen application.propertiesDateien arbeiten, versuchen Sie, Ihren Wert zur Eigenschaftendatei des übergeordneten Projekts hinzuzufügen .

Wenn Sie sich nicht sicher sind, welches Ihr übergeordnetes Projekt ist, überprüfen Sie die pom.xmlDatei Ihres Projekts auf ein <parent>Tag.

Dies löste das Problem für mich.

Janac Meena
quelle
0

Sie können EnvironmentClass verwenden, um Daten abzurufen:

@Autowired
private Environment env;
String prop= env.getProperty('some.prop');
Abd Abughazaleh
quelle