스프링 프레임워크로 진행을 하다보면, 무언가 동적으로 컨트롤러를 다시 태워서 데이터를 가져오고 싶을 때가 있다. 단지 this만으로 처리하기에는 클래스가 많이 찢어져있고 이쁘지도 않다.
그래서 첫 번째로 찾아 본것이 “Spring bean 가져오기” 였다.
코드는 다음 처럼 나왔다.
- Class clazz = WebApplicationContextUtils.getWebApplicationContext(request.getSession(false).getServletContext()).getBean(targetClassName).getClass();
- if (clazz != null) {
- Object obj = clazz.newInstance();
- Method method = clazz.getDeclaredMethod(targetMethodName, HttpServletRequest.class, HttpServletResponse.class);
- result = (ModelAndView) method.invoke(obj, request, reponse);
- }
저러면 동적인 메서드 인보크도 가능하….지만 주의할점은 bean 객체가 아닌 class를 가져온것이므로 newInstance()를 통해 생성된 인스턴스는 내부에 만일 Autowire어노테이션이 존재할때 해당부분이 null이 되어있을 것이다. 뿐만아니라 만약 이쪽 url로 리퀘스트가 집중되면 newInstance로 인해서 OOM쪽에도 신경이 써지게 될것이다.
자 가만 생각해보자…
“어차피 WAS가 로드될때 Spring이 클래스를 bean으로 인스턴스화 하잖아?”
그렇다…
우린 걍 객체를 스프링으로부터 빌려 쓰면 되는 것이다.
사실 위 코드에서 getBean()이후에 .getClass()와 newInstance()는 의미가 없다.
왜?
인스턴스니까!
- Object beanInstance = WebApplicationContextUtils.getWebApplicationContext(request.getSession(false).getServletContext()).getBean(targetClassName);
- if (beanInstance != null) {
- Class beanClass = beanInstance.getClass();
- Method method = beanClass.getDeclaredMethod(targetMethodName, HttpServletRequest.class, HttpServletRequest.class);
- if(method != null){
- ModelAndView result = (ModelAndView) method.invoke(beanInstance, request, request);
- }
- }
사실 getBean()을 통해 나오는 Object는 해당 Class의 Instance이다… 우린 걍 getClass()를 통해 메서드 정보를 가져오고 getBaean()에서 얻은 스프링 빈객체로 인보크하면 되는거다. 값은 result에 담겨있다.
JSP 예)
<%@ page import="org.springframework.web.context.support.WebApplicationContextUtils" %>
UserDao dao = (UserDao)WebApplicationContextUtils(request.getSession(false).getServletContext()).getBean("userDao");