[원리]_04_자동 설정 만들기 2부 : @ConfigurationProperties

2 minute read

자동 설정 만들기 2부 : @ConfigurationProperties

  • 덮어쓰기 방지하기
    • @ConditionalOnMissingBean
  • 빈 재정의 수고 덜기
    • @ConfigurationProperties(“holoman”)
    • @EnableConfigurationProperties(HolomanProperties)
    • 프로퍼티 키값 자동 완성
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-configuration-processor</artifactId>
	<optional>true</optional>
</dependency>

앞서 강의에서 발생했던 문제점을 해결해보자

자동 설정 파일 문제점

명시적으로 Holoman 빈을 등록하는 경우, 스프링부트 어플리케이션이 빈을 2단계로 등록하기 때문에, 먼저 @ComponentScan으로 우리가 작성한 빈등록 코드로 Holoman이 빈으로 등록된다. 그리고나서 @EnableAutoConfiguration로 읽어온 빈을 등록하려고 하기 때문에 (1)오버라이딩이 막혀있어 어플리케이션이 실행되지 않는다. (2)AutoConfiguration 설정으로 재정의 돼서 빈으로 등록되어 실행된다.

해결방법 1. @ComponentScan 이 무조건 우선시되도록 한다.

  • (자동 설정을 구현한 프로젝트에서)

  • 자동 설정 파일에 @ConditionalOnMissingBean 어노테이션 추가

holoman 빈이 존재하지 않는 경우에만 AutoConfiguration 설정에 따라 빈을 등록한다.

이미 ComponentScan으로 빈이 등록된 상황이라면 다시 빈을 만들지 않게 된다.

@Configuration
public class HolomanConfiguration {

    @Bean
    @ConditionalOnMissingBean // <-- 어노테이션 추가
    public Holoman holoman() {
        Holoman holoman = new Holoman();
        holoman.setHowLong(5);
        holoman.setName("Solar");
        return holoman;
    }
}

위와 같이 코드를 수정 후, build → install (CLI : mvn install)

  • ([spring-boot-getting-started] 프로젝트에서) 의존성 refresh

image-20200901194348098

다시 실행해보면 명시적으로 등록한 빈의 설정값으로 잘 출력되는 것을 확인할 수 있다.

image-20200901180013662

⇒ 스프링부트가 제공하는 여러가지 기본 설정(기능)들을 커스터마이징할 수 있는 기본 방법 중 하나이다.

해결방법 2. 내가 굳이 빈을 등록하는 코드까지 써야할까? 빈의 설정 값만 변경하고 싶다.

빈을 재정의하는 수고를 덜어보자

빈 자동 설정 시, application.properties 파일에서 속성값을 읽어와 빈을 생성하도록 코드를 수정
  • (자동 설정을 구현한 프로젝트에서)

[src] > [main] > [java] > [resources] > application.properties 파일 생성

holoman.name = solarccc
holoman.how-long = 55

( * howLong 변수 명은 동일하게 camel case로 작성해도 되고, dash(-)를 써도 된다. )

  • properties 를 쓰려면 별도로 정의를 해줘야 한다.

(1) HolomanProperties.java 파일 생성

@ConfigurationProperties("prefix") 어노테이션 추가 - prefix에 사용할 이름을 적어준다.

package dev.solar;

import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties("holoman")
public class HolomanProperties {

    private String namek;

    private int howLong;

    public String getNamek() {
        return namek;
    }

    public void setNamek(String namek) {
        this.namek = namek;
    }

    public int getHowLong() {
        return howLong;
    }

    public void setHowLong(int howLong) {
        this.howLong = howLong;
    }
}

(2) 의존성 추가

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <optional>true</optional>
</dependency>

( → 여기까지해서 오류메시지가 나옴. @EnableConfigurationProperties 설정을 해주면 사라진다. )

(3) 설정한 properties 값을 사용하도록 HolomanConfiguration 클래스 편집

  • @EnableConfigurationProperties(HolomanProperties.class) 어노테이션 추가

  • 빈 주입 받음
  • 속성값을 HolomanProperties.class 로 부터 가져와서 사용
@Configuration
@EnableConfigurationProperties(HolomanProperties.class) //HolomanProperties 를 사용하겠다고 선언
public class HolomanConfiguration {

    @Bean
    @ConditionalOnMissingBean
    public Holoman holoman(HolomanProperties properties) { //HolomanProperties 빈을 주입받음
        Holoman holoman = new Holoman();
       // Before
       // holoman.setHowLong(5);
       // holoman.setName("Solar");
       // After
        holoman.setHowLong(properties.getHowLong());
        holoman.setName(properties.getName());
        return holoman;
    }
}

위와 같이 코드를 수정 후, build → install (CLI : mvn install)

자동 설정을 properties를 이용해 다른 프로젝트에서 사용
  • ([spring-boot-getting-started] 프로젝트에서) 의존성 refresh

[src] > [main] > [java] > [resources] > application.properties 파일 생성

holoman.name = solarcc
holoman.how-long = 999
@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication application = new SpringApplication(Application.class);
        application.setWebApplicationType(WebApplicationType.NONE); //좀 더 빨리 실행되도록 타입 변경
        application.run(args);
    }

  // Holoman 빈을 정의하는 코드를 삭제
//    @Bean
//    public Holoman holoman() {
//        Holoman holoman = new Holoman();
//        holoman.setName("Solariri");
//        holoman.setHowLong(60);
//        return holoman;
//    }
}

실행결과

Holoman{name='solarcc', howLong=999}

⇒ 빈을 재정의하지 않고, application.properties 의 값을 변경하는 것만으로 설정 값을 바꿀 수 있다.

@Conditional..xxx 어노테이션이 다양하다.

이름으로 어떤 상황에 쓰이는 빈인지 추측할 수 있다. 이를 통해 AutoConfiguration 설정을 읽을 수 있으므로, AutoConfiguration의 Properties를 읽으면 어떻게 커스터마이징할 수 있을지 감을 잡을 수 있다. → 3부 활용 파트에서