ค่า Spring Boot application.properties ไม่ได้เติมข้อมูล


97

ฉันมีแอป Spring Boot ที่เรียบง่ายมากที่ฉันกำลังพยายามทำงานกับการกำหนดค่าภายนอก ฉันได้พยายามติดตามข้อมูลในเอกสารสปริงบูตแล้วแต่ฉันชนถนนกั้น

เมื่อฉันรันแอปด้านล่างคอนฟิกูเรชันภายนอกในไฟล์ application.properties ไม่ได้รับการเติมข้อมูลลงในตัวแปรภายใน bean ฉันแน่ใจว่าฉันกำลังทำอะไรโง่ ๆ ขอบคุณสำหรับคำแนะนำ

MyBean.java (อยู่ใน / 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 (อยู่ใน / 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 (อยู่ใน / src / main / resources /)

some.prop=aabbcc

บันทึกเอาต์พุตเมื่อเรียกใช้แอป Spring Boot:

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

4
และควร@Valueเปลี่ยนอย่างไรก่อนสร้างถั่ว? วิธี "ตรวจจับ" ของคุณหากตั้งค่าไม่ถูกต้อง ในขณะนั้นจะเป็นโมฆะเสมอและ@Valueจะถูกประมวลผลหลังจากการสร้างวัตถุ
M. Deinum

คำตอบ:


165

วิธีที่คุณทำการฉีดคุณสมบัติจะไม่ได้ผลเนื่องจากการฉีดเสร็จสิ้นหลังจากที่มีการเรียกตัวสร้าง

คุณต้องดำเนินการอย่างใดอย่างหนึ่งต่อไปนี้:

ทางออกที่ดีกว่า

@Component
public class MyBean {

    private final String prop;

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

โซลูชันที่ใช้งานได้ แต่ทดสอบได้น้อยกว่าและอ่านได้น้อยกว่าเล็กน้อย

@Component
public class MyBean {

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

    public MyBean() {

    }

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

โปรดทราบว่าไม่ใช่ Spring Boot เฉพาะ แต่ใช้กับแอปพลิเคชัน Spring ใด ๆ


ฉันต้องเพิ่มคำอธิบายประกอบ @Autowired ให้กับตัวสร้างเพื่อให้มันใช้งานได้
Sébastien Tromp

1
ขอบคุณสำหรับทิป. สิ่งนี้ควรอยู่ในเอกสาร Spring ที่พูดถึงคำอธิบายประกอบ @Value แต่ดูเหมือนว่าคนเหล่านั้นจะไม่สนใจคำติชมเกี่ยวกับเอกสารของพวกเขา :(
Alex Worden

1
ช่วยฉันประหยัดค่าใช้จ่าย ขอบคุณ!
Robert Moskal

1
@geoand จะเป็นอย่างไรถ้าคุณมีค่ามากกว่า 10 ค่าคุณจะต้องพิมพ์ทั้งหมด 10 ค่าในแบบที่คุณทำหรือไม่? หรือมีวิธีที่สะอาดกว่านี้
Jesse

1
@Jackie แน่นอนมีวิธีที่สะอาดกว่านี้! ตรวจสอบ@ConfigurationPropertiesและ@EnableConfigurationPropertiesคำอธิบายประกอบ
geoand

5

ผู้ใช้ "geoand" ถูกต้องในการชี้เหตุผลที่นี่และให้วิธีแก้ปัญหา แต่แนวทางที่ดีกว่าคือการห่อหุ้มคอนฟิกูเรชันของคุณลงในคลาสแยกต่างหากพูดว่าคลาส SystemContiguration java จากนั้นฉีดคลาสนี้ลงในบริการที่คุณต้องการใช้ฟิลด์เหล่านั้น

วิธีปัจจุบันของคุณ (@grahamrb) ในการอ่านค่ากำหนดค่าลงในบริการโดยตรงนั้นเกิดข้อผิดพลาดได้ง่ายและจะทำให้เกิดอาการปวดหัวในการปรับโครงสร้างใหม่หากเปลี่ยนชื่อการตั้งค่าการกำหนดค่า


จะไม่ปวดหัวน้อยกว่านี้ได้อย่างไรหากคุณมีคลาสแยกต่างหากสำหรับคุณสมบัตินั้น? คุณจะยังมีสตริงที่ต้องจำเมื่อทำการ refactoring
dot_Sp0T

4
มีที่เดียวที่คุณต้อง "จำ" ไม่ใช่เลข N ค่าสเกลาร์ที่มีอยู่บน SystemContiguration ทำให้คุณพิมพ์ได้ดี นอกจากนี้หากมีตรรกะทางธุรกิจที่มี "ส้อม" ~~~ ตามค่าที่มาจากการกำหนดค่า ~~~ ..... จะเป็นการดีกว่าที่จะฉีดบางสิ่งลงในคลาส / businessLogic ที่ต้องการค่า Aka มันง่ายกว่ามากที่จะล้อเลียน SystemContiguration จากนั้นพยายามให้ @Value ทำงานทั่วทุกที่
granadaCoder

3

อันที่จริงสำหรับฉันด้านล่างใช้งานได้ดี

@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 + "================== ");
   }

}

ตอนนี้ทุกที่ที่ฉันต้องการเพียงแค่เรียกร้อง

MyBean.prop

มันจะคืนค่า


2

คำตอบนี้อาจใช้ได้กับกรณีของคุณหรือไม่ก็ได้ ... เมื่อมีอาการคล้าย ๆ กันนี้และตรวจสอบโค้ดซ้ำหลายครั้งและทุกอย่างดูดี แต่การ@Valueตั้งค่าก็ยังไม่มีผล แล้วหลังจากทำFile > Invalidate Cache / Restartด้วยIntelliJ (IDE ของฉัน) ปัญหาก็หายไป ...

วิธีนี้ทำได้ง่ายมากดังนั้นอาจคุ้มค่ากับการยิง


1

การใช้คลาส Environment เราจะได้รับแอปพลิเคชัน ค่าคุณสมบัติ

@ อัตโนมัติ,

private Environment env;

และเข้าถึงโดยใช้

String password =env.getProperty(your property key);

0

ทำตามขั้นตอนเหล่านี้ 1: - สร้างคลาสการกำหนดค่าของคุณตามที่คุณเห็นด้านล่าง

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: - เมื่อคุณมีคลาสคอนฟิกูเรชันให้ฉีดตัวแปรจากคอนฟิกูเรชันที่คุณต้องการ

@Component
public class YourService {

    @Autowired
    private String getsomePro;

    // now you have a value in getsomePro variable automatically.
}

0

หากคุณกำลังทำงานในโปรเจ็กต์แบบหลายโมดูลขนาดใหญ่ที่มีapplication.propertiesไฟล์ต่างๆหลายไฟล์ให้ลองเพิ่มมูลค่าของคุณลงในไฟล์คุณสมบัติของโปรเจ็กต์หลัก

หากคุณไม่แน่ใจว่าเป็นโปรเจ็กต์หลักของคุณให้ตรวจสอบpom.xmlไฟล์ของโปรเจ็กต์ของคุณเพื่อหา<parent>แท็ก

สิ่งนี้ช่วยแก้ปัญหาให้ฉันได้


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.