스프링으로 개발을 하다보면 종종 bean 클래스가 아닌 일반 클래스에서도 Bean 클래스를 사용해야 하는 경우가 있다. 이때 ApplicationContext
인터페이스를 이용하면 간단히 구현이 가능한데, 어떻게 하면 static 하게 사용할 수 있을까? 한 번 알아보자.
JDK 8
Spring boot 2.5.0
public class BeanContext {
private static ApplicationContext context;
public static void init(ApplicationContext context){ // 1. applicationContext 를 주입받을 메서드
BeanContext.context = context;
}
public static <T> T get(Class<T> clazz){
return context.getBean(clazz);
}
}
@RequiredArgsConstructor // 2.1 롬복 생성자를 이용해 주입
@SpringBootApplication
public class WebTestApplication {
private final ApplicationContext context; // 2. 실제 applicationContext 를 주입받는다.
public static void main(String[] args) {
SpringApplication.run(WebTestApplication.class, args);
}
@PostConstruct
public void init(){
BeanContext.init(context); // 3. 객체의 생명주기를 이용해 스태틱 참조변수에 주입한다.
} // 스프링 앱이 정상적으로 기동된 후에 주입된다.
}
@Service
public class TestService {
public String testMessage() {
return "testMessage";
}
}
@RestController
public class TestController {
@GetMapping
public String test() {
// 4. 컨트롤러 bean 에 TestService 객체를 선언/주입받지 않고도
// 간단히 사용할 수 있다.
return BeanContext.get(TestService.class).testMessage();
}
}
Bean 컴포넌트 사용 이외에도 @Value
를 이용하여 application.properties(yml)
의 속성값을 가져와야 하는 경우도 종종 있는데 이 또한 스프링에서 제공하는 Environment
인터페이스를 이용하여 간단히 해결할 수 있다.
public class PropertyUtils {
private static Environment environment(){
// 1. BeanContext 의 applicationContext 에서 바로 Environment 의 객체를 받아온다.
return BeanContext.get(Environment.class);
}
public static String getProperty(String key){
return environment().getProperty(key);
}
}
@RestController
public class TestController {
@GetMapping("/{key}")
public String bean(@PathVariable String key){
String value = PropertyUtils.getProperty(key); // 2. 바로 property 값을 호출한다.
return value;
}
}
위와같이 @PostConstruct 어노테이션을 이용하여 간단히 스태틱 참조변수에 주입해줘서 application 전역적으로 참조하여 사용할 수 있음을 알 수 있었다.
@PostConstruct 어노테이션의 경우 JDK 9 부터는 Deprecated 되었기 때문에 JDK9 버전 이후부터는 스프링의 InitializingBean 인터페이스를 사용하거나 javax.annotation 의존성을 추가하면 된다.