我有一个非常简单的 Spring Boot 应用程序,我正在尝试使用一些外部配置。我尝试按照 spring boot documentation 上的信息进行操作,但遇到了障碍。
当我在 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
@Value
?如果设置了值,您“检测”的方式是错误的。那时它始终为 null,因为 @Value
将在对象构造之后处理。
您执行属性注入的方式将不起作用,因为注入是在调用构造函数之后完成的。
您需要执行以下操作之一:
更好的解决方案
@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 应用程序
用户“geoand”在这里指出原因并给出解决方案是正确的。但更好的方法是将您的配置封装到一个单独的类中,例如 SystemContiguration java 类,然后将该类注入到您想要使用这些字段的任何服务中。
您当前将配置值直接读取到服务中的方式(@grahamrb)容易出错,并且如果更改配置设置名称会导致重构问题。
这个答案可能适用于您的情况,也可能不适用......一旦我有类似的症状并且我多次检查我的代码并且一切看起来都很好,但 @Value
设置仍然没有生效。然后在用我的 IntelliJ
(我的 IDE)做 File > Invalidate Cache / Restart
之后,问题就消失了......
这很容易尝试,所以可能值得一试
实际上,对我来说,下面的工作正常。
@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
它将返回值。
使用环境类,我们可以得到应用程序。属性值
@自动连线,
private Environment env;
并使用
String password =env.getProperty(your property key);
将无参数构造函数代码移动到 PostConstruct 对我来说已经成功了。因为它将保持默认的 bean 加载工作流完好无损。
@Component
public class MyBean {
@Value("${some.prop}")
private String prop;
@PostConstruct
public void init() {
System.out.println("================== " + prop + "================== ");
}
}
按着这些次序。 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.
}
如果您正在处理具有多个不同 application.properties
文件的大型多模块项目,请尝试将您的值添加到 父 项目的属性文件中。
如果您不确定哪个是您的父项目,请检查您的项目的 pom.xml
文件中的 <parent>
标记。
这为我解决了这个问题。
您可以使用 Environment
类来获取数据:
@Autowired
private Environment env;
String prop= env.getProperty('some.prop');
为我解决了这个问题的最简单的解决方案:
向需要填充 @Value
字段的组件/服务添加 @PropertySource
注释:
@Service
@PropertySource("classpath:myproperties.properties")
public class MyService {
@Value("${some.prop}")
private String someProperty;
// some logic...
}
确保将属性文件添加到与您的服务/组件相同的模块的资源文件夹中。
您收到此错误是因为您正在使用 new 关键字初始化类。为了解决这个问题,首先你需要创建配置类,在这个类下你需要创建这个类的bean。当您使用 bean 调用它时,它将起作用..
package ca.testing;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.sql.Connection;
import java.sql.DriverManager;
@Component
@PropertySource("db.properties")
public class ConnectionFactory {
@Value("${jdbc.user}")
private String user;
@Value("${jdbc.password}")
private String password;
@Value("${jdbc.url}")
private String url;
Connection connection;
public Connection getConnection(){
try {
connection = DriverManager.getConnection(url, user, password);
System.out.println(connection.hashCode());
}catch (Exception e){
System.out.println(e);
}
return connection;
}
public static void main(String[] args) {
AnnotationConfigApplicationContext context= new AnnotationConfigApplicationContext(Config.class);
ConnectionFactory connectionFactory= context.getBean(ConnectionFactory.class);
connectionFactory.getConnection();
}
}
在我从不同的类(如(new Bean())中删除关键字 new 后,我的应用程序属性正在挑选
@ConfigurationProperties
和@EnableConfigurationProperties
注释