개발관련/(과거)메모

자바 Reflect Class, Method

동팡 2017. 4. 29. 15:48

참고

http://mysnyc.tistory.com/42

이 친구가 설명한거 응용해서 내거에 적용했다.

자바 Reflect Method 


run.java는 Reflect.java를 상속받는다.(run -> 자식 reflect -> 부모)

즉 run.java는 reflect.java를 확장하며 2개의 코드는 별개의 파일이다.



run.java (main)

public void doOperateOptional() throws Exception {
		String METHODE_NAME_PROCESS;
		Method methodProcess;
		Object[] methodParamObject = null;
		Class[] methodParamClass;
		
		for (VOAttribute a : attributeList) {
			METHODE_NAME_PROCESS = "insert" + a.getTag();
			try {
				methodParamClass = new Class[] { dao.getClass(), a.getClass()};
				methodParamObject = new Object[] { dao, a };
				
				methodProcess = this.getClass().getMethod(
						METHODE_NAME_PROCESS, methodParamClass);  
				methodProcess.invoke(this, methodParamObject);
			} catch( java.lang.NoSuchMethodException e ) {
				
			}
		}	
	}




Reflect.java (run class와 다른 class)

   

public void insertName(Dao dao, VOAttribute a) throws Exception {
		VOManagedObject_Names VOmanagedObject_Names = new VOManagedObject_Names();
		VOmanagedObject_Names.setManagedObjectID(VOmanagedObject.getId())
				.setNameID(a.getID());

		dao.insertManagedObjectNames(VOmanagedObject_Names);		
	}
	
	public void insertObject(Dao dao, VOAttribute a) throws Exception {
		VOManagedObject_Object VOmanagedObject_Object = new VOManagedObject_Object();
		VOmanagedObject_Object.setManagedObjectID(VOmanagedObject.getId())
				.setObjectID(a.getID());
		
		dao.insertManagedObjectObject(VOmanagedObject_Object);
	}
	
	public void insertApplicationnformation(Dao dao, VOAttribute a) throws Exception {
		VOManagedObject_ApplicationInformation VOmanagedObject_ApplicationInformation = 
				new VOManagedObject_ApplicationInformation();
		VOmanagedObject_ApplicationInformation.setManagedobjectID(VOmanagedObject.getId())
				.setApplicationinformationID(a.getID());
		
		dao.insertManagedObjectApplicationInformation(VOmanagedObject_ApplicationInformation);
	}
	
	public void insertCustomAttribute(Dao dao, VOAttribute a) throws Exception {
		VOManagedObject_CustomAttributes VOmanagedObject_CustomAttributes =
				new VOManagedObject_CustomAttributes();
		VOmanagedObject_CustomAttributes.setManagedObjectID(VOmanagedObject.getId())
				.setCustomAttributeID(a.getID());
		
		dao.insertManagedObjectCustomAttributes(VOmanagedObject_CustomAttributes);
	}	


주의: 캡슐화를 위해 접근 지정자(Protected)를 설정할 경우 접근을 못한다.

RunTime 에서는 run.java가 reflect.java를 상속받도록 확장(extends) 해도 안된다.


찾아봤다. 


Method.setAccessible(true) 


삽질하니까 된다. Run.java를 아래와 같이 약간 수정했다. 

@Override
	public void doOperateOptional() throws Exception {
		String METHODE_NAME_PROCESS;
		Method methodProcess;
		Object[] methodParamObject;
		Class[] methodParamClass;
		Class reflectClass = ServerDoGenerateOperation.class;

for (VOAttribute a : attributeList) { METHODE_NAME_PROCESS = "insert" + a.getTag(); try { methodParamClass = new Class[] { dao.getClass(), a.getClass()}; methodParamObject = new Object[] { dao, a }; methodProcess = reflectClass.getDeclaredMethod( METHODE_NAME_PROCESS, methodParamClass); methodProcess.setAccessible(true); methodProcess.invoke(this, methodParamObject); } catch (NoSuchMethodException e ) { } } }


@methodParamClass: invoke하고자 하는 method에 전달 인자의 데이터 형 또는 클래스 이름을 미리 지정한다. 

@methodParam: 전달 인자로 보내고자 하는 데이터(실체)를 미리 저장한다.

- Method 객체에 invoke하고자 하는 ServerDoGenerateOperation.class 클래스의 메소드(매개변수, 매개변수 ....) 를 지정한다.

@Method.setAccessible(true): Runtime에서도 접근 지정자 private 또는 protected의 접근을 허용한다.

@Method.invoke(Object, param, param....): 현재 객체(this)와 미리 저장한 param 값을 대입하면 끝


getMethod vs getDeclaredMethod

getDeclaredMethod: 호출하고자 하는 클래스의 선언된 메소드만 찾는다.

getMethod: 호출하고자 하는 클래스에 선언된 메소드를 탐색 후, 상위 클래스를 탐색한다.(public method만 찾는다.) 

참고 : http://stackoverflow.com/questions/17953724/using-getdeclaredmethod-to-get-a-method-from-a-class-extending-another


자바 Reflect Class

런타임에서 어떤 클래스를 실행하는지 알 수 있고, 동적으로 클래스를 로드해야할 경우 

나의 경우는 Operation마다 실행해야할 클래스가 다 다른다.


일단

인터페이스 생성 후, Interface에는 doOperate 공통 메소드 선언 (맨 하위 클래스가 오버라이딩 한다.)

String operationClass는 불러오고자 하는 클래스명을 동적으로 받아 온다. 

operationClass는 class.getName + 'Operation명' 이다.

클래스 파일이름을 OperationCreate, OperationDelete 이다. 



String operationClass = decodeHelperSupport.getOperationClass();
Class clazz = Class.forName(operationClass);
ServerDoOperation ServerOperator = (ServerDoOperation)clazz.newInstance();

ServerOperator.doOperate();

그리고 실행, 설명하기 귀찮다. 생략 

궁금하면 댓글 달아주세요. 예제 파일 만들게요