programing

application.properties의 값을 정적 변수에 할당하려면 어떻게 해야 합니까?

kakaobank 2023. 4. 2. 11:35
반응형

application.properties의 값을 정적 변수에 할당하려면 어떻게 해야 합니까?

MVC를.는 나나 a a a가 있다UserService「」가 .@Service많은 정적 변수를 가지고 있습니다. fileapplication.properties의 .

application.properties가 있습니다.SVN_URL = http://some.url/repositories

에는 다음과 같은 것이 .@Value("${SVN_URL}") private static String SVN_URL

iInstantiation of bean failed; nested exception is java.lang.ExceptionInInitializerError

@Autowired private static Environment env;

다음에 : :: :private static String SVN_URL=env.getProperty("SVN_URL");

같은 에러가 발생합니다.

★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★도 보유하지 않아도 됩니다.application.properties태태틱스패트릭이 제안하는 '회피책'은 매우 지저분합니다.

  • 이 정적 필드가 언제 수정되었는지 알 수 없습니다.
  • 어떤 스레드가 값을 수정하는지 알 수 없습니다.
  • 어떤 스레드라도 이 정적 필드의 값을 언제든지 변경할 수 있으며 사용자는 나사로 전환됩니다.
  • 프라이빗 스태틱필드를 초기화하는 방법은 의미가 없습니다.

콩을 제어하면@Service주석 작성을 스프링 컨테이너에 위임합니다.Spring은 어플리케이션 전체에서 공유되는 빈을 1개만 생성하여 이 빈의 라이프 사이클을 제어합니다(물론 이 동작은 변경할 수 있지만 여기서는 기본 동작을 참조합니다).에는 아무런.스프링에서는 합니다. 스프링은 하나의 인스턴스만 있음을 확인합니다.UserService또한 설명한 오류가 발생합니다.스프링 컨테이너가 기동하기 전에 정적 필드의 초기화가 많은 프로세서 사이클에서 발생하기 때문입니다.여기서 정적 필드가 초기화되는 시기에 대한 자세한 내용을 확인할 수 있습니다.

제안.

다음과 같은 작업을 수행하는 것이 훨씬 좋습니다.

@Service
public class UserService {
    private final String svnUrl;

    @Autowired
    public UserService(@Value("${SVN_URL}") String svnUrl) {
        this.svnUrl = svnUrl;
    }
}

이 접근방식은 다음과 같은 몇 가지 이유로 적합합니다.

  • 생성자 주입은 개체를 초기화하는 데 필요한 값을 직접 설명합니다.
  • final는 이 합니다.

「」를 사용합니다.@ConfigurationProperties

여러 속성을 하나의 클래스에 로드하는 다른 방법도 있습니다.컨피규레이션클래스에 로드하는 모든 값에 프레픽스를 사용해야 합니다.다음의 예를 검토해 주세요.

@ConfigurationProperties(prefix = "test")
public class TestProperties {

    private String svnUrl;

    private int somePort;

    // ... getters and setters
}

은 봄을 견딜 수 있다.TestProperties initialization 초기화('클래스 초기화')를)testPropertiescontainerbean)에 이할 수 . 여기 가 있습니다.application.properties일일: :

test.svnUrl=https://svn.localhost.com/repo/
test.somePort=8080

Baldung은 이 주제에 대한 멋진 글을 블로그에 올렸습니다. 저는 더 많은 정보를 얻기 위해 그것을 읽을 것을 추천합니다.

대체 솔루션

으로든 정적 클래스를 public static final필드 inside - 클래스 로더가 이 클래스를 로드하고 응용 프로그램 수명 동안 변경되지 않을 때 이러한 값이 인스턴스화됩니다.의 문제는 의 '봄로드할 수 것입니다.application.properties파일에서는 코드로 직접 관리해야 합니다(또는 속성 파일에서 이러한 상수의 값을 로드하는 클래스를 구현할 수도 있지만, 이것은 해결하려는 문제에 대해 매우 상세하게 들립니다).

스프링에서는 정적 변수에 값을 주입할 수 없습니다.

회피책으로는 스태틱하지 않은 세터를 생성하여 값을 스태틱 변수에 할당합니다.

@Service
public class UserService {

    private static String SVN_URL;

    @Value("${SVN_URL}")
    public void setSvnUrl(String svnUrl) {
        SVN_URL = svnUrl;
    }

}

정적 멤버 함수의 application.properties에는 액세스할 수 없습니다.다만, 다음의 회피책이 있습니다.

application.properties

server.ip = 127.0.0.1

특성.Extractor.java

public class PropertiesExtractor {
     private static Properties properties;
     static {
        properties = new Properties();
        URL url = new PropertiesExtractor().getClass().getClassLoader().getResource("application.properties");
        try{
            properties.load(new FileInputStream(url.getPath()));
           } catch (FileNotFoundException e) {
                e.printStackTrace();
           }
        }

        public static String getProperty(String key){
            return properties.getProperty(key);
        }
}

Main.class

public class Main {
    private static PropertiesExtractor propertiesExtractor;
    static{
         try {
             propertiesExtractor = new PropertiesExtractor();
         } catch (UnknownHostException e) {
               e.printStackTrace();
           }
    }

    public static getServerIP(){
        System.out.println(propertiesExtractor.getProperty("server.ip")
    }
}
static String profile;

@Value("${spring.profiles.active:Unknown}")
private void activeProfile(String newprofile) {
    profile = newprofile;
};

Spring Boot 속성에 대한 정적 액세스를 얻으려면 명령줄 러너 인터페이스를 구현하는 Properties Holder 컴포넌트를 만듭니다.명령줄 러너 인터페이스는 Spring Boot에 의한 컴포넌트 인스턴스화 시 run()을 실행합니다.

Properties의 Properties 객체에 대한 자동 액세스가 있기 때문에홀더 컴포넌트에서는 run() 메서드의 CommandLineRunner 실행 시 자동 배선 속성을 정적 속성 클래스 변수에 할당할 수 있습니다.

이 시점에서 모든 클래스가 정적으로 속성을 호출할 수 있습니다.Holder.getProperties()를 사용하여 Spring Boot 속성 값의 내용에 액세스합니다.

특성.Holder.class:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

@Component
public class PropertiesHolder implements CommandLineRunner {

    //Spring Boot Autowired Properties Object
    @Autowired MyProperties myAutowiredProperties;

    //Statically assigned Properties Object
    private static MyProperties properties;

    //Hide constructor (optional)
    private PropertiesHolder(){}

    public static MyProperties getProperties() throws NullPointerException{
        if(PropertiesHolder.properties == null)
            throw new NullPointerException("Properites have not been initialized by Spring Application before call.");

        return PropertiesHolder.properties;
    }

    //Use to assign autowired properties to statically allocated properties
    public static void makeAvailable(MyProperties myAutowiredProperties){
        PropertiesHolder.properties = myAutowiredProperties;
    }

    //Spring Boot command line runner autoexecuted upon component creation
    //which initializes the static properties access
    public void run(String... args) {
        PropertiesHolder.makeAvailable(myAutowiredProperties);
    }
}

MyProperties.class

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

//Example: your_properties_file_prefix.properties 
@ConfigurationProperties(prefix = "YOUR_PROPERTIES_FILE_PREFIX") 
@Component
@Data
public class MyProperties {

    private String property1;
    private String property2;
    private String property3;
}

컨피규레이션파일을 포함한 심플한 솔루션이 적어도1개 이상 있습니다.

@Configuration
public class YourStaticPropertyConfiuration {
  public static String PROPERTY_NAME;

  @Value("${propertyName}")
  public void setProperty(final String propertyName) {
    PROPERTY_NAME = propertyName;
  }
}

PROPERTY_NAME을 정적 변수로 사용

어떤 이유로든 파일에서 가져온 설정 속성을 정적 속성으로 제공하고자 하는 모든 사용자를 위해 가능한 한 간단하고 안전한 솔루션이 있습니다.

문제:

Spring Boot unfortunately doesn't provide a simple way to import properties from a file and bind them as static properties to a class. One possible solution to achieve that anyway would be to set the static properties using `@Value` annotations like this:
public class GlobalProperties {

    public static String NAME;

    @Value("${configs.boss.name}")
    public void setName(String name) {
        NAME = name;
    }
}

이 에서는, final로서 할 수 .
그리고 우리는 확실히 그것을 원하지 않는다.

솔루션:

application.yml:

configs:
  boss:
    name: "Leeloo Multipass"

Config Properties(구성 속성)자바:


@Validated
@ConfigurationProperties(prefix = "configs")
public record ConfigProperties(@NotNull Boss boss) {

    public static final String BOSS_NAME = BOSS.NAME;

    private static class Boss {

        private static String NAME;

        public Boss(String name) {
            NAME = name;
        }
    }
}

이 솔루션은 Spring Boot이 구성 개체를 먼저 구축하고 속성 구성 개체를 먼저 구축하는 것을 전제로 합니다.를 「Spring Boot」라고 합니다.Bean 된 는 이미 있습니다.또, 도 행해집니다.또한 스태틱속성의 초기화도ConfigProperties는 네스트된 클래스의 스태틱속성에 액세스 할 수 있습니다(이러한 속성은 아직 최종은 아니지만 외부에서 액세스 할 수 없습니다). 하면 렇렇음음음음음음음음음음 as as as as as as as as as라고 선언된 할 수 .static finalSpring Boot에서 내부 초기화 프로세스를 변경하지 않는 한 모든 것은 크림과 쿠키입니다.

이 접근방식은 Spring Boot 3 및 Java 17에서 테스트되었습니다.물론 configs-bean을 통해 속성을 추가할 수도 있습니다.그러기 위해서는 네스트된 클래스의 속성을 명시적으로 지정하고 대응하는 getter를 구현해야 합니다.이 경우 클래스 대신 레코드를 사용하면 어느 정도 단순화할 수 있습니다.

언급URL : https://stackoverflow.com/questions/45192373/how-to-assign-a-value-from-application-properties-to-a-static-variable

반응형