[Spring Boot #5] 스프링 부트 자동 설정 만들기 : @ConditionalOnMissingBean, @ConfigurationProperties
| 사용자(Custom) Autoconfigure 클래스 선언의 문제점
@Configuration 어노테이션을 등록하여 Autoconfigure 스프링 부트 자동 설정을 만들었지만 여기에 문제점이 있습니다.
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication application = new SpringApplication(Application.class);
application.setWebApplicationType(WebApplicationType.NONE);
application.run(args);
}
@Bean
public Saelobi saelobi(){
Saelobi saelobi = new Saelobi();
saelobi.setName("KBS2");
saelobi.setHowLong(50);
return saelobi;
}
}
@Component
public class AppRunner implements ApplicationRunner {
@Autowired
Saelobi saelobi;
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println(Saelobi.class);
System.out.println(saelobi);
}
}
만일 @EnableAutoConfiguration 어노테이션을 통한 스프링 빈이 주입되었을 경우 어떤 특별한 이유로 이 빈을 다시 재정의하여 쓸 시에는 다음과 같은 에러 문구가 뜨면서 재정의 시도가 차단됩니다.
***************************
APPLICATION FAILED TO START
***************************
Description:
The bean 'saelobi', defined in class path resource [com/tutorial/AutoConfig.class], could not be registered. A bean with that name has already been defined in com.tutorial.springboot.Application and overriding is disabled.
Action:
Consider renaming one of the beans or enabling overriding by setting spring.main.allow-bean-definition-overriding=true
| @ConditionalOnMissingBean을 통한 충돌 요소 해결
위 오버라이딩 충돌을 해소하려면 자동 설정 부분을 Maven 프로젝트를 통해 만들시 @ConditionalOnMissingBean 어노테이션을 추가해야합니다. 이 어노테이션은 스프링 부트 프로젝트 상에서 동명의 스프링 빈이 정의되었을 시에는 쓰지 않고 그 스프링 빈을 쓰며 만약 없을 시에는 자동 등록한 빈을 쓰게 끔 유도하는 용도로 쓰입니다.
@Configuration
public class AutoConfig {
@Bean
@ConditionalOnMissingBean
public Saelobi saelobi(){
Saelobi saelobi = new Saelobi();
saelobi.setHowLong(5);
saelobi.setName("KBS");
return saelobi;
}
}
다시 mvn install 을 실행하여 local repository에 등록할 경우 이번에는 충돌했던 부분이 해소되고 스프링 부트에 등록됬던 saelobi 빈이 주입되는 것을 알 수 있습니다.
class com.tutorial.Saelobi
Saelobi{name='KBS2', howLong=50}
| @ConfigurationProperties를 통한 자동 설정 클래스 만들기
자동 설정 클래스 내의 스프링 빈을 재정의 할 때 코드 상에서가 아닌 property 파일을 통해 재정의 하고자 할 때는 @ConfigurationProperties 어노테이션을 통해 설정파일로도 재정의가 가능하도록 코드를 작성해야 합니다.
먼저 pom.xml에 다음과 같은 dependency를 추가해야 합니다.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
public class Saelobi {
String name;
int howLong;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getHowLong() {
return howLong;
}
public void setHowLong(int howLong) {
this.howLong = howLong;
}
@Override
public String toString() {
return "Saelobi{" +
"name='" + name + '\'' +
", howLong=" + howLong +
'}';
}
}
다음 property 파일을 통해 값을 가져오는 역할을 하는 클래스를 작성합니다.
@ConfigurationProperties("saelobi")
public class SaelobiProperties {
private String name;
private int howLong;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getHowLong() {
return howLong;
}
public void setHowLong(int howLong) {
this.howLong = howLong;
}
}
다음 @EnableConfigurationPropertes 어노테이션을 통해 위 클래스를 프로퍼티 파일 정보를 담고 있는 클래스로 자동 등록하게 합니다.
@Configuration
@EnableConfigurationProperties(SaelobiProperties.class)
public class AutoConfig {
@Bean
@ConditionalOnMissingBean
public Saelobi saelobi(SaelobiProperties properties){
Saelobi saelobi = new Saelobi();
saelobi.setHowLong(properties.getHowLong());
saelobi.setName(properties.getName());
return saelobi;
}
}
mvn install을 한 후 위 프로젝트를 local repository에 등록합니다.
| Property 파일을 통한 자동 설정 스프링 빈을 재정의
다음과 같은 스프링 부트 구조를 만듭니다. 여기서 중요한 것은 application.properties 파일의 존재입니다.
# application.properties saelobi.name = KBS_NEW
saelobi.how-long = 90
위 Maven 프로젝트를 통해 만든 dependency 추가는 다음과 같습니다.
<dependency>
<groupId>com.tutorial</groupId>
<artifactId>autoconfigure</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
이제 어플리케이션을 실행하면 application.properties에 설정한 값을 읽어와 saelobi 빈을 재정의하게 됩니다.
@Component
public class AppRunner implements ApplicationRunner {
@Autowired
Saelobi saelobi;
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println(Saelobi.class);
System.out.println(saelobi);
}
}
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication application = new SpringApplication(Application.class);
application.setWebApplicationType(WebApplicationType.NONE);
application.run(args);
}
}
class com.tutorial.Saelobi
Saelobi{name='KBS_NEW', howLong=90}
'Spring Framework > Spring boot #2' 카테고리의 다른 글
[Spring Boot #9] 스프링 부트 외부 설정, 설정값 검증 (0) | 2021.03.15 |
---|---|
[Spring Boot #8] 이벤트 리스너 및 웹 어플리케이션 타입 지정, 커맨드 인수 처리( Event Listener, Application Type, Command Arguments ) (0) | 2021.03.15 |
[Spring Boot #7] 스프링부트(Spring Boot) HTTPS 구축, HTTP2, 다중 커넥터 설정 (0) | 2021.03.15 |
[Spring Boot #6] 스프링 부트 내장 웹 서버 톰캣(tomcat) 설정 (0) | 2021.03.15 |
[Spring Boot #4] 스프링 부트 자동 설정 만들기 : Starter, AutoConfigure (0) | 2021.03.15 |
[Spring Boot #3] 스프링 부트 의존성 관리 (Spring Boot Dependency Management) (0) | 2021.03.15 |
[Spring Boot #2] 스프링 부트 프로젝트 구조 (Spring Boot Project Structure) (0) | 2021.03.15 |
[Spring Boot #1] 인텔리제이(IntelliJ)로 스프링 부트 프로젝트 시작하기 (0) | 2021.03.15 |