Spring 스프링 - @Conditional 조건 별 Bean 생성하기

salgu·2023년 3월 5일
0

Spring

목록 보기
1/22
post-thumbnail

@Conditional은 Spring Bean을 조건에 맞춰 등록할때 사용됩니다.

dev, staging, production 상황 별로 등록해야 되는 Spring Bean이 다를수가 있습니다.
개발 환경에서만 작동해야 되고 실제 운영 환경에서는 작동하면 안될 기능이 있는 등 Bean등록에 조건이 필요할때 사용됩니다.

실습해볼 예제는 Memory를 가져오는 class를 Bean으로 등록하여 호출하면 메모리 사용량을 보여주는 예제 입니다.



Setting


MemoryFinder.java

@Slf4j
public class MemoryFinder {

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

    public Memory get() {
        // Runtime.getRuntime() JVM 에서 메모리 정보를 실시간으로 조회
        long max = Runtime.getRuntime().maxMemory();
        long total = Runtime.getRuntime().totalMemory();
        long free = Runtime.getRuntime().freeMemory();
        long used = total - free;
        return new Memory(used, max);
    }
}

메모리 사용량을 조회해오는 core 기능을 가진 class입니다.
여기서 Bean으로 등록하지 않고 Config 설정을 통해 직접 등록해주는 방식을 사용하겠습니다.

MemoryController.java

@Slf4j
@RestController
@RequiredArgsConstructor
public class MemoryController {

    private final MemoryFinder memoryFinder;

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

MemoryFinder를 주입받아 호출하는 용도로 사용되는 RestController입니다.

MemoryConfig.java

@Configuration
public class MemoryConfig {

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

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

MemoryFinder를 Bean으로 직접 등록해주고 MemoryController에도 주입해주어 직접 등록해줍니다.

Setting 결과

이렇게 Bean들을 등록하게 된다면 production에서 사용하고 싶지 않아도 Bean들이 등록되어 사용할 수 있는 상황이 만들어집니다.
이때 조건을 통해 Bean을 만들기 위해 Conditional이라는 Annotaion을 사용해 조건문을 만들어 해결할 수 있습니다.



@Conditional 적용


Condition.java (Interface)

@FunctionalInterface
public interface Condition {
	boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);
}

Spring에는 Condition이라는 Interface가 존재하고 해당 인터페이스의 구현체를 구현해주면 손쉽게 조건별로 Bean 등록을 할 수 있습니다.

MemoryCondition.java (Condition Interface 구현)

@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);
    }
}

Condition이라는 interface를 상속받아 Memory 빈 등록에 조건을 달아줄 MemoryCondition을 구현해줍니다.
property에 "memory"의 key가 "on"이라면 빈 등록을 해주는 조건입니다.

MemoryConfig.java

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

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

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

직접 Memory 관련 Class들을 등록해주는 Configuration에 Condition을 구현한 Class를
@Conditional 어노테이션에 넣어주면 적용이 완료됩니다.

결과

해당 프로젝트 property에 memory=on을 넣어줘야 Memory 관련 Class들이 작동하는것을 확인할 수 있고
실행 환경 등 변경에 맞게 유연하게 Bean등록을 변경할 수 있게 되었습니다.





reference:

profile
https://github.com/leeeesanggyu, leeeesanggyu@gmail.com

0개의 댓글