如何以编程方式重写 Spring Boot application.properties?

我有 jdbc 属性文件,这些文件是从外部配置 Web-service 获取的 在 Spring boot 中,为了设置 mysql props,只需将它们添加到 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

我怎样才能在我的应用程序中以编程方式覆盖它们?

春季批量道具也是如此:

database.driver=com.mysql.jdbc.Driver
database.url=jdbc:mysql://localhost/mydv
database.username=root
database.password=root
105292 次浏览

You can add additional property sources in a lifecycle listener reacting to ApplicationEnvironmentPrepared event.

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:

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.

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:

<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

<jee:jndi-lookup id="dataSource"
jndi-name="java:comp/env/jdbc/loader-batch-dataSource" lookup-on-startup="true"
resource-ref="true" cache="true" />

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.

The easiest way is to set the properties at the time the SpringApplication is defined. The basic example below sets the tomcat port to 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);
}
}

This is how you can override the application.properties programatically if you have to.

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


}

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

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.

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.

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

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:

    @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.

Add string to your Application 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);
}


}