vm옵션값에 따라 Bean 등록하는법(스프링, 스프링부트)(@Conditional)

2023. 3. 19. 18:04개발

반응형

스프링부트 이미지

만약 특정 Vm옵션이 들어온 경우에만 메모리를 확인하고 싶다면..?
해당 내용은 김영한님 강의 스프링 부트 - 핵심 원리와 활용에 나오는 내용입니다.
별개의 라이브러리로 제공된다는 가정하에 진행된 내용이고, 개인적인 정리를 위한 내용입니다.

Memory 클래스

import lombok.Getter;
import lombok.ToString;

@Getter
@ToString
public class Memory {

    private Long used;
    private Long max;

    public Memory(Long used, Long max) {
        this.used = used;
        this.max = max;
    }
}

컨트롤러

@Slf4j
@RestController
@RequiredArgsConstructor
public class MemoryController {
    private final MemoryFinder memoryFinder;

    @GetMapping("/memory")
    public Memory system() {
        Memory memory = memoryFinder.get();
        log.info("memory = {}", memory.toString());
        return memory;
    }
}

MemoryFinder 클래스

@Slf4j
public class MemoryFinder {
    public Memory get() {
        long max = Runtime.getRuntime().maxMemory();
        long total = Runtime.getRuntime().totalMemory();
        long free = Runtime.getRuntime().freeMemory();
        long used = total - free;
        return new Memory(used, max);
    }

    @PostConstruct
    public void init() {
        log.info("init memoryFinder");
    }
}

같은 소스 코드이지만 특정 상황일 때 만 특정 빈들을 등록해서 사용 하도록 도와 주는 어노테이션이다. 스프링에서 제공하는 기능..!

@Conditional

스프링에서 제공하는 인터페이스이다.

# VM Options
# jar 파일 실행시 -Dmemory=on -jar project.jar

만약 현재 사용중인 메모리를 확인하고 특정 환경변수가 있을 때만 빈으로 등록해서 확인하고 싶다면..?

스프링에서 제공하는 Condition에 matches를 구현하고 그걸 사용하면 된다고 한다.

import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;

@Slf4j
public class MemoryCondition  implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        // -Dmemory=on
        String memory = context.getEnvironment().getProperty("memory");
        log.info("memory = {}", memory);
        return "on".equals(memory);
    }
}

해당 기능을 사용하기 위해서 만약 특정 빈들을 등록해야 한다면 아래와 같이 설정 할 수 있다.

@Configuration
@Conditional(MemoryCondition.class)
public class MemoryConfig {

    @Bean
    MemoryController memoryController() {
        return new MemoryController(memoryFinder());
    }

    @Bean
    MemoryFinder memoryFinder() {
        return new MemoryFinder();
    }
}

결론적으로는 VM옵션으로 추가정보로 on이라는 특정 값이 있어야지만 빈을 등록하고 동작하게 되는 것이다..!!

그리고 그런걸 다 구현해둔 스프링부트 어노테이션이 존재한다..

ConditionalOnProperty

@Configuration
@ConditionalOnProperty(name = "memory", havingValue = "on")
public class MemoryConfig {

    @Bean
    MemoryController memoryController() {
        return new MemoryController(memoryFinder());
    }

    @Bean
    MemoryFinder memoryFinder() {
        return new MemoryFinder();
    }
}

해당 클래스의 내부에 들어가보면 @Conditional(OnPropertyCondition.class)

OnPropertyCondition 클래스에서 동일하게 특정 조건이 들어왔을때 비교하는 부분을 상세하게 구현해둔걸 확인 할 수 있다..!

반응형