Java 프레임워크 만들기 - JSP

자바 리플렉션 메서드 동적 실행 - Java Reflection Method invoke, 이클립스(Eclipse)

carrotweb 2021. 4. 20. 16:07
728x90
반응형

클래스("getClass"로 가져온 "Class<?>")의 "getMethod"메서드는 메서드 명과 파라미터 타입 배열(Class<?>[] parameterTypes)로 구성된 메서드를 클래스에서 찾아서 메서드 객체(java.lang.reflect.Method)를 넘겨줍니다.

getMethod(String name, Class<?>... parameterTypes) or getMethod(String name)

"name"은 메서드 명입니다.

"parameterTypes"는 클래스(java.lang.Class)로된 구성된 배열입니다. 파라미터가 없으면 입력하지 않습니다.

클래스에 ".class"를 사용하면 클래스의 패키지명과 클래스 명으로 구성된 클래스(Class<>)를 가져옵니다.

예를 들어, "String"에 ".class"로 "String"의 클래스(Class<>)를 가져오겠습니다.

System.out.println("String.class = " + String.class);

[Console]
String.class = class java.lang.String

 

"invoke"메서드는 메서드 객체(java.lang.reflect.Method)를 호출하여 실행시킵니다.

invoke(Object obj, Object... args) or invoke(Object obj)

"obj"은 메서드가 있는 클래스 인스턴스(클래스를 "new"로 생성되거나 "newInstance()"으로 생성된 객체(Object)) 입니다.

"args"는 메서드에 전달되는 파라미터로 객체(Object)로 구성된 배열입니다. 파라미터가 없으면 입력하지 않습니다.

테스를 위해 "TestDispatcherServlet.java"에서 "/test2.do"로 호출될 때 실행되는 "TestService2"의 "process"를 "getMethod"메서드와 "invoke"메서드로 호출되게 수정하겠습니다.

 

"TestService2"의 생성과 "process"호출을 주석으로 처리합니다.

} else if ("/test2.do".equals(requestURI)) {
	//TestService2 testService2 = new TestService2();
	//testService2.process(request);
	requestDispatcher = request.getRequestDispatcher("/WEB-INF/jsp/testservlet.jsp");
}

"Class.forName(String name)"메서드로 "TestService2"를 찾고 인스턴스를 생성합니다.

try {
	Class<?> finedClass = Class.forName("com.home.project.test2.service.TestService2");
	System.out.println("Class.forName : " + finedClass.getName());
	Object classInstance = finedClass.newInstance();
	System.out.println("Class Instance : " + classInstance);
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
	e.printStackTrace();
}

자바 클래스 동적 로딩하기(carrotweb.tistory.com/53)를 참고하시면 됩니다.

 

"TestService2.java"파일입니다.

public class TestService2 {
	public void process(HttpServletRequest request) {
		request.setAttribute("name", "영희");
	}
}

 

"process"메서드는 1개의 파라미터로 "HttpServletRequest"를 받습니다. 그래서 1개인 "Class"배열을 생성하고 "HttpServletRequest.class"로 배열에 추가합니다.

Class<?>[] parameterTypes = new Class[1];
parameterTypes[0] = HttpServletRequest.class;

 

클래스("finedClass")에서 "process"메서드를 찾습니다.

"getMethod"에 메서드 명("process")과 위에서 생성한 파라미터 타입 배열을 입력합니다.

Method method = null;
try {
	method = finedClass.getMethod("process", parameterTypes);
	System.out.println("Class Method : " + method.getName() + "를 찾았습니다.");
} catch (NoSuchMethodException | SecurityException e1) {
	e1.printStackTrace();
}

 

메서드에 전달할 1개의 파라미터 배열을 생성하고 "HttpServletRequest"의 변수인 "request"를 입력합니다.

Object parameter[] = new Object[1];
parameter[0] = request;

 

 

메서드를 "invoke"로 호출합니다.

"invoke"생성된 인스턴스("classInstance")와 위에서 생성한 파라미터 배열을 입력합니다.

try {
	method.invoke(classInstance, parameter);
	System.out.println("Class Method : " + method.getName() + "를 호출하였습니다.");
} catch (IllegalArgumentException | InvocationTargetException e) {
	e.printStackTrace();
}

 

"process"메서드가 "void"임으로 리턴 값(Object)을 받지 않았습니다. "void"가 아니라면 형 변환을 통해 처리하시면 됩니다.

 

"Servers"탭에서 "tomcat8"를 선택하고 "start"버튼(start the server)을 클릭합니다. 웹 브라우저에서 "http://localhost:8080/test2/test2.do"를 입력합니다.

 

"Console"탭을 클릭하면 "TestService2"클래스를 동적으로 생성하고 "process"를 찾아 호출된 것을 확인할 수 있습니다.

 

웹 페이지에 "전체 세션 수 : null, 현제 세션 수 : null"로 노출된 것은 "TestService2"의 "process"에 "TestSessionCounter"싱글톤과 "request"에 속성이 없어서 그렇습니다. 추가해주시면 됩니다.

request.getSession().setMaxInactiveInterval(1000);
TestSessionCounter testSessionCounter = TestSessionCounter.getInstance();
request.setAttribute("sessionTotalCount", testSessionCounter.getTotalCount());
request.setAttribute("sessionCount", testSessionCounter.getCount());

 

728x90
반응형