[TIL] Spring: How to Inject Spring Bean into Static Variable
포스트
취소

[TIL] Spring: How to Inject Spring Bean into Static Variable

Spring bean을 static variable(정적 변수)에 저장하는 것이 유용하거나 편리할 경우가 있다. 예를 들면 Environment.activeProfiles의 값을 그렇게 활용할 수 있다.

사실 이렇게 static variable에 의존하는 클래스는 테스트하기 더 어려워지므로 static variable이 아닌 constructor를 통해 DI 받는 것이 더 좋은 패턴이라고 할 수 있다. 하지만 간단한 케이스에서는 이 방법이 유용할 수 있다.

Inject Spring bean in constructor

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
private val logger = KotlinLogging.logger {}

@Component
class MyUtil(environment: Environment) {
    companion object {
        private var isProd: Boolean? = null
        fun isProd(): Boolean = isProd
            ?: (System.getProperty("spring.profiles.active", "prod") == "prod")
    }

    init {
        isProd = environment.activeProfiles.contains("prod")
        logger.info("isProd: $isProd")
    }
}

가장 간단한 방법은 위와 같이 static variable을 가진 클래스를 bean으로 등록하고 생성자에서 static variable을 초기화해주는 것이다.

Note: Bean registration order

이렇게 초기화된 static variable을 사용할 때 주의할 점이 있다. bean 등록(초기화) 순서이다.

1
2
3
4
5
6
7
8
@Service
class MyService {
    private val isProd = MyUtil.isProd() // static variable 초기화 전에 호출될 수도 있음
    
    fun f() {
        println(isProd)
    }
}

MyUtil, MyService bean들의 초기화 순서가 정의되어 있지 않기 때문에 초기화 전에 참조가 발생할 수 있다. Spring bean 클래스에 @Order 어노테이션은 초기화 순서가 아닌 정렬 순서를 정의한다.

@Order in Spring: https://www.baeldung.com/spring-order

방법 1: @DependsOn

@DependsOn이라는 어노테이션을 통해 bean 생성 순서를 정의할 수는 있다.

Controlling Bean Creation Order with @DependsOn Annotation: https://www.baeldung.com/spring-depends-on

방법 2: Do not refer while bean initialization (초기화 중에 참조하지 않기)

또다른 방법으로, 가능하다면 해당 참조를 초기화 이후 시점으로 연기하는 것이다.

1
2
3
4
5
6
@Service
class MyService {
    fun f() {
        println(MyUtil.isProd())
    }
}

여전히 변수로 사용하고 싶다면, lazy delegator를 활용할 수도 있다.

lazy prop: https://kotlinlang.org/docs/delegated-properties.html#observable-properties

1
2
3
4
5
6
7
8
@Service
class MyService {
    private val isProd: Boolean by lazy { MyUtil.isProd() }

    fun f() {
        println(isProd)
    }
}

Conclusion

Spring bean을 static variable로 DI하고, 이렇게 사용할 때의 유의사항들과 노하우들을 알아보았다.

이렇게 사용하는 방식은 클래스의 테스트를 더 어렵게 만들 수 있기 때문에, 꼭 필요한 상황에만 사용하는 것이 좋다.

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.

[TIL] Elasticsearch: How-to index rollover

[TIL] Gradle: dependency cache path in Home directory