[英]How can I override Spring Boot application.properties programmatically?
I have jdbc property files which I take from external configuration web-service In spring boot in order to set mysql props it's easy as adding those to application.properties:我有 jdbc 属性文件,我从外部配置 Web 服务中获取在 spring 引导中,为了设置 mysql 道具,将它们添加到 application.properties 很容易:
spring.datasource.url=jdbc:mysql://localhost/mydb
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
How could I override those programticlly in my app?我怎么能在我的应用程序中覆盖那些程序?
same goes for Spring-batch props: Spring-batch 道具也是如此:
database.driver=com.mysql.jdbc.Driver
database.url=jdbc:mysql://localhost/mydv
database.username=root
database.password=root
You can add additional property sources in a lifecycle listener reacting to ApplicationEnvironmentPrepared event.您可以在对 ApplicationEnvironmentPrepared 事件做出反应的生命周期侦听器中添加其他属性源。
Something along the lines of:类似的东西:
public class DatabasePropertiesListener implements ApplicationListener<ApplicationEnvironmentPreparedEvent> {
public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
ConfigurableEnvironment environment = event.getEnvironment();
Properties props = new Properties();
props.put("spring.datasource.url", "<my value>");
environment.getPropertySources().addFirst(new PropertiesPropertySource("myProps", props));
}
}
Then register the class in src/main/resources/META-INF/spring.factories:然后在 src/main/resources/META-INF/spring.factories 中注册该类:
org.springframework.context.ApplicationListener=my.package.DatabasePropertiesListener
This worked for me, however, you are sort of limited as to what you can do at this point as it's fairly early in the application startup phase, you'd have to find a way to get the values you need without relying on other spring beans etc.这对我有用,但是,由于在应用程序启动阶段还很早,您此时可以做的事情受到了一定的限制,您必须找到一种方法来获得所需的值,而无需依赖其他弹簧豆类等
Just to provide another option to this thread for reference as when I started to look for an answer for my requirement this came high on the search list, but did not cover my use case.只是为了为此线程提供另一个选项以供参考,因为当我开始为我的要求寻找答案时,这在搜索列表中名列前茅,但没有涵盖我的用例。
I was looking to programmatically set spring boot property at start up, but without the need to work with the different XML/Config files that spring supports.我希望在启动时以编程方式设置 spring 引导属性,但不需要使用 spring 支持的不同 XML/配置文件。
The easiest way is to set the properties at the time the SpringApplication is defined.最简单的方法是在定义 SpringApplication 时设置属性。 The basic example below sets the tomcat port to 9999.
下面的基本示例将 tomcat 端口设置为 9999。
@SpringBootApplication
public class Demo40Application{
public static void main(String[] args){
SpringApplication application = new SpringApplication(Demo40Application.class);
Properties properties = new Properties();
properties.put("server.port", 9999);
application.setDefaultProperties(properties);
application.run(args);
}
}
Since spring boot 1.3 EnvironmentPostProcessor is available for this purpose.由于 spring boot 1.3 EnvironmentPostProcessor可用于此目的。 Create a subclass of it and register in META-INF/spring.factories A good example is here :
创建它的子类并在 META-INF/spring.factories 中注册一个很好的例子是这里:
https://github.com/spring-cloud/spring-cloud-sleuth/blob/48f3f9783f277a795d0210399f0ea09b7f1a4e71/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/autoconfig/TraceEnvironmentPostProcessor.java https://github.com/spring-cloud/spring-cloud-sleuth/blob/48f3f9783f277a795d0210399f0ea09b7f1a4e71/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/sleuth/autoonconfigment/Postraceor
As of Spring Boot 2.0.X, you can dynamically override individual properties (for example, in a unit test) using a combination of a custom ApplicationContextInitializer and the ContextConfiguration annotation.从 Spring Boot 2.0.X 开始,您可以使用自定义 ApplicationContextInitializer 和 ContextConfiguration 注释的组合动态覆盖单个属性(例如,在单元测试中)。
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.PortTest.RandomPortInitailizer;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.context.support.TestPropertySourceUtils;
import org.springframework.util.SocketUtils;
import static org.assertj.core.api.Assertions.assertThat;
@RunWith(SpringRunner.class)
@SpringBootTest
@ContextConfiguration(initializers = RandomPortInitializer.class)
public class PortTest {
@Autowired
private SomeService service;
@Test
public void testName() throws Exception {
System.out.println(this.service);
assertThat(this.service.toString()).containsOnlyDigits();
}
@Configuration
static class MyConfig {
@Bean
public SomeService someService(@Value("${my.random.port}") int port) {
return new SomeService(port);
}
}
static class SomeService {
private final int port;
public SomeService(int port) {
this.port = port;
}
@Override
public String toString() {
return String.valueOf(this.port);
}
}
public static class RandomPortInitializer
implements ApplicationContextInitializer<ConfigurableApplicationContext> {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
int randomPort = SocketUtils.findAvailableTcpPort();
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(applicationContext,
"my.random.port=" + randomPort);
}
}
}
This is how you can set properties during startup if you are running spring boot application.如果您正在运行 Spring Boot 应用程序,这就是在启动期间设置属性的方法。
The easiest way is to set the properties before you even started an app.最简单的方法是在启动应用程序之前设置属性。
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication application = new SpringApplication(Application.class);
ConfigurableEnvironment env = new ConfigurableEnvironment();
env.setActiveProfiles("whatever");
Properties properties = new Properties();
properties.put("server.port", 9999);
env.getPropertySources()
.addFirst(new PropertiesPropertySource("initProps", properties));
application.setEnvironment(env);
application.run(args);
}
}
It could be very simple:这可能非常简单:
@SpringBootApplication
public class SampleApplication {
public static void main(String[] args) {
new SpringApplicationBuilder(SampleApplication.class)
.properties(props())
.build()
.run(args);
}
private static Properties props() {
Properties properties = new Properties();
properties.setProperty("MY_VAR", "IT WORKS");
return properties;
}
}
application.yml应用程序.yml
test:
prop: ${MY_VAR:default_value}
If you need to do this for testing purposes: since spring-test 5.2.5 you can use @DynamicPropertySource
:如果您出于测试目的需要这样做:从 spring-test 5.2.5 开始,您可以使用
@DynamicPropertySource
:
@DynamicPropertySource
static void setDynamicProperties(DynamicPropertyRegistry registry) {
registry.add("some.property", () -> some.way().of(supplying).a(value) );
}
Takes precedence over pretty much all of the other ways of supplying properties.优先于几乎所有其他提供属性的方式。 The method must be static though.
该方法必须是静态的。
With this Method in your configuration you can set default properties.在您的配置中使用此方法,您可以设置默认属性。
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class)
.properties("propertyKey=propertyValue");
}
This is how you can override the application.properties programatically if you have to.如果需要,您可以通过这种方式以编程方式覆盖 application.properties。
public static void main(String[] args) {
SpringApplication app = new SpringApplication(Restdemo1Application.class);
app.setAdditionalProfiles("dev");
// overrides "application.properties" with "application-dev.properties"
app.run(args);
}
Add string to your Application class将字符串添加到您的应用程序 class
@SpringBootApplication
public class Application {
public static void main(String[] args) {
System.setProperty("spring.config.location",
"file:///D:/SpringProjects/SpringBootApp/application.properties");
SpringApplication.run(Application.class, args);
}
}
Under META-INF folder create exactly this folders and file: spring>batch>override>data-source-context.xml and in your xml file make sure to override the paramters you want like this:在 META-INF 文件夹下准确创建此文件夹和文件: spring>batch>override>data-source-context.xml 并在您的 xml 文件中确保覆盖您想要的参数,如下所示:
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${loader.jdbc.driver}" />
<property name="url" value="${loader.jdbc.url}" />
<property name="username" value="${loader.jdbc.username}" />
<property name="password" value="${loader.jdbc.password}" />
</bean>
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
or use a jndi like this in the xml file to access your external configuration file like catalina.properties或者在 xml 文件中使用这样的 jndi 来访问你的外部配置文件,比如 catalina.properties
<jee:jndi-lookup id="dataSource"
jndi-name="java:comp/env/jdbc/loader-batch-dataSource" lookup-on-startup="true"
resource-ref="true" cache="true" />
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.