리플렉션으로 생성한 객체에 Bean 주입하기

이게 필요한 경우가 생겼는데 난 당연히 안되겠지 하면서 ChatGPT에 물어보니 가르쳐줌;; 시발;;

다음 경우를 말한다.

@Component
class HolyShitHelper {
 public String holyShit() {
  return "Holy Moly...";
 }
}

얘를 사용하고 싶은데 로직 상 리플렉션에 의해 생성된 객체 안에서는 Bean을 넣을 방법이… 없… 는 줄 알았는데 있다. 저 홀리쉿헬퍼를 사용하는 서비스가 다음과 같이 생겼다고 하면

class HolyShitService {
 private HolyShitHelper holyShitHelper;

 @Autowired
 public void setHolyShitHelper(HolyShitHelper holyShitHelper)  {
  this.holyShitHelper = holyShitHelper;
 }

 public String serveHolyShit() {
  return holyShitHelper.holyShit();
 }
}

서비스레이어야 사실 @Service 어노테이션 써서 빈으로 만드는데 그냥 저런게 있다 치고, 저걸 다른 곳에서 리플렉션을 이용해서 인스턴스를 만들어서 사용하고 싶다고 합시다.

@Component
class HolyShitServer {
 public String serveHolyShit() throws Exception {
  var constructor = HolyShitService.class.getConstructor();
  var service = constructor.newInstance();
  return service.servceHolyShit();
 }
}

HolyShitService는 Spring에서 관리하는 객체가 아니므로 @Autowired를 넣더라도 주입이 안된다. 그리고 빈이 아닌 곳에서 @Autowired를 쓰면 IDE에선 떽!!! 하면서 빨간줄을 그어주는데 사실 다음 소개할 방법으로 제대로 주입하면 실행은 된다. IDE 경고를 없애려면 일단 다음과 같이 경고를 무시할 수 있다.

@SuppressWarning("SpringJavaInjectionPointsAutowiringInspection")
class HolyShitService {
 // 생략
}

그리고 HolyShitServer에서 다음 방법으로 하면 HolyShitHelper를 주입할 수 있다.

@Component
class HolyShitServer {
 private ApplicationContext applicationContext;

 @Autowired
 public void setApplicationContext(ApplicationContext applicationContext) {
  this.applicationContext = applicationContext;
 }

 public String serveHolyShit() throws Exception {
  var constructor = HolyShitService.class.getConstructor();
  var service = constructor.newInstance();
  var beanFactory = applicationContext.getAutowireCapableBeanFactory()
  beanFactory.autowireBean(service);
  return service.servceHolyShit();
 }
}

로 하면 잘 된다.

참고로 코틀린으로도 잘 된다.

끗.

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다