programing

Spring Boot application.properties를 프로그래밍 방식으로 덮어쓰려면 어떻게 해야 합니까?

mailnote 2023. 4. 1. 09:42
반응형

Spring Boot application.properties를 프로그래밍 방식으로 덮어쓰려면 어떻게 해야 합니까?

외부 구성 웹 서비스에서 가져온 jdbc 속성 파일을 가지고 있습니다.봄 부팅 시 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

내 앱에 있는 프로그램들을 덮어쓰려면 어떻게 해야 하나요?

스프링 배치 소품도 마찬가지입니다.

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

ApplicationEnvironmentPrepared 이벤트에 반응하는 라이프사이클 리스너에 속성 소스를 추가할 수 있습니다.

다음과 같은 것들이 있습니다.

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

그런 다음 src/main/resources/META-INF/spring.factories에 클래스를 등록합니다.

org.springframework.context.ApplicationListener=my.package.DatabasePropertiesListener

이 방법은 효과가 있었습니다만, 아직 애플리케이션 기동 단계이기 때문에, 현시점에서는 할 수 있는 일이 한정되어 있기 때문에, 다른 스프링 콩 등에 의존하지 않고 필요한 가치를 얻을 수 있는 방법을 찾아야 합니다.

요건에 대한 답을 찾기 시작했을 때 참조용으로 이 스레드에 다른 옵션을 제공하기 위해 검색 목록에서 상위 항목이 되었지만 사용 사례에 대해서는 다루지 않았습니다.

기동시에 spring boot 속성을 프로그래밍 방식으로 설정하려고 했습니다만, spring이 서포트하고 있는 다른 XML/Config 파일을 조작할 필요는 없습니다.

가장 쉬운 방법은 Spring Application 정의 시 속성을 설정하는 것입니다.다음 기본 예에서는 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);
    }
}

스프링 부트 1.3 Environment Post Processor를 이 목적으로 사용할 수 있습니다.서브클래스를 생성하여 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

Spring Boot 2.0.X 에서는 커스텀 Application Context Initializer 와 Context Configuration 주석의 조합을 사용하여 (유닛테스트 등) 개개의 속성을 동적으로 덮어쓸 수 있습니다.

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

이 해야 하는 : 이므로 spring-test 5.2.5를 사용할 수 .@DynamicPropertySource:

    @DynamicPropertySource
    static void setDynamicProperties(DynamicPropertyRegistry registry) {
        registry.add("some.property", () -> some.way().of(supplying).a(value) );
    }

자산을 공급하는 다른 모든 방법보다 우선합니다.단, 메서드는 스태틱해야 합니다.

이것은 매우 단순할 수 있습니다.

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

스프링 부트 애플리케이션을 실행하고 있는 경우는, 기동시에 속성을 설정할 수 있습니다.

가장 쉬운 방법은 앱을 시작하기도 전에 속성을 설정하는 것입니다.

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

구성에서 이 방법을 사용하여 기본 속성을 설정할 수 있습니다.

@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(Application.class)
              .properties("propertyKey=propertyValue");
}

이렇게 하면 필요에 따라 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);

}

응용 프로그램 클래스에 문자열 추가

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

}

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>

또는 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" />

언급URL : https://stackoverflow.com/questions/29072628/how-can-i-override-spring-boot-application-properties-programmatically

반응형