본문 바로가기

spring/boot

스프링 부트 자동 구성과 실패분석기

스프링 부트 자동 구성

스프링 부트에서 제공하는 스타터 라이브러리를 가져오면 자동으로 관련 설정을 해준다.

이러한 설정은 @Configuration 애너테이션이 붙어있는 클래스를 통해서 자동으로 필요한 빈을 생성해주는 것이다.

하지만 특정 상황에서 정의된 빈을 생성하지 않고 싶은 경우를 대비해서 스프링 부트는 @Conditional 애너테이션을 제공한다.

 

@Conditional

스프링이 관리하는 컴포넌트의 생성을 제어할 수 있도록 @Bean, @Component, @Configuration과 더불어서 @Conditional
애너테이션을 제공한다.

이 애너테이션은 Condition 클래스를 인자로 받는다. Condition은 이름처럼 조건을 검사하는 책임을 가지는 함수형 인터페이스로 matches()
메서드를 정의하고 있다.

 

고수준 @Conditional

스프링에서 다양한 조건에서 사용할 수 있는 고수준 인터페이스를 제공하고 있다.

애너테이션 예시 설명
@ConditionalOnBean @ConditionalOnBean(DataSource.class) 설정에서 DataSource 빈이 명시되어 있으면 true
@ConditionalOnClass @ConditionalOnClass(DataSource.class) 클래스 패스에 DataSource 클래스가 있으면 true
@ConditionalOnProperty @ConditionalOnProperty("some.property") some.property 프로퍼티가 정의되어 있으면 true
@ConditionalOnCloudPlatform @ConditionalOnCloudPlatform(CloudPlatform.KUBERNETES) CloudPlafrom 이 쿠버네티스로 설정되면 true
@ConditionalOnExpression @ConditionalOnExpression("SPEL expression) spel 표현식이 true이면 true
@ConditionalOnJava @ConditionalOnJava(JavaVersion.EIGHT) 자바 8이라면 true
@ConditionalOnJndi @ConditionalOnJndi("java:/com/env/jdbc/MyLocalDB") 지정한 JNDI 컨텍스트가 존재하면 true
@ConditionalOnMissingBean @ConditionalOnMissingBean(DataSource.class) DataSource 빈이 설정되어 있지 않으면 true
@ConditionalOnMissingClass @ConditionalOnMissingClass(DataSource.class) 클래스 패스에 DataSource 클래스가 없으면 true
@ConditionalOnNotApplication @ConditionalOnNotApplication 웹 애플리케이션이 아니면 true
@ConditionalOnResource @ConditionalOnResource("classpath:some.properties") some.properties 파일이 클래스 패스에 있으면 true
@ConditionalOnSingleCandidate @ConditionalOnSingleCandidate(DataSource.class) DataSource 빈이 한 개만 정의되어 있으면 true
@ConditionalOnWebApplication @ConditionalOnWebApplication 웹 어플리테이션이면 true

 


실패분석기

스프링에서 특정 설정을 잘못하면 실패의 원인을 분석해주는 출력을 해주는데 이를 담당하는 것인 실패분석기 이다.

애플리케이션의 초기 설정시에 잘못된 설정이 있다면 그 원인을 상세히 설명해주는 분석기를 사용자가 만들 수 있다.

커스텀 실패분석기를 만들기 위해서는 다음 절차가 필요하다.

  1. 커스텀 예외 설정
public class UrlNotAccessibleException extends RuntimeException {
    private final String url;

    public UrlNotAccessibleException(String url){
        this(url, null);
    }

    public UrlNotAccessibleException(String url, Throwable cause) {
        super("URL " + url + " is not accessible", cause);
        this.url = url;
    }

    public String getUrl() {
        return url;
    }
}
  1. AbstractFailureAnalyzer를 상속받은 커스텀 실패 분석기 정의
public class UrlNotAccessibleFailureAnalyzer extends AbstractFailureAnalyzer<UrlNotAccessibleException> {
}
  1. 분석기의 실패 분석 매서드 analyze() 구현
public class UrlNotAccessibleFailureAnalyzer extends AbstractFailureAnalyzer<UrlNotAccessibleException> {
    @Override
    protected FailureAnalysis analyze(Throwable rootFailure, UrlNotAccessibleException cause) {
        System.out.println("hello");
        return new FailureAnalysis("Unable to access the URL=" + cause.getUrl(),
                "Validate the URL and ensure it is accessible", cause);
    }
}
  1. resources/META_INF/spring.factories 에 실패 분석기 등록
org.springframework.boot.diagnostics.FailureAnalyzer=\
  com.example.spring_boot_example.chapter4.exception.UrlNotAccessibleFailureAnalyzer
  1. 원하는 검증 로직 구현 후 해당 메서드에 @EventListener로 매핑한다.
@Component
public class UrlAccessibilityHandler {

    @Value("${api.url:https://www.navuder.com/}")
    private String url;

    @EventListener(classes = ContextRefreshedEvent.class)
    public void listen(){
        // 외부 API URL에 접근 할 수 없는 상태를 만들기 위해
        // 의도적으로 UrlNotAccessibleException 예외를 던지도록 설정
        if(url.contains("naver")) return;
        throw new UrlNotAccessibleException(url);
    }
}]

REFERENCE

도서 - 실전 스프링 부트