본문 바로가기

백엔드 개발/SpringMVC

관심사 분리와 MVC 패턴의 원리(1)

1. 클래스의 매개변수 정보를 보여주는 예제 

public class MethodInfo {
	public static void main(String[] args) throws Exception{

		
		// 1. YoilTeller 클래스의 객체를 생성
     		// YoilTeller 클래스의 모든 정보를 가진 클래스 객체 생성 (Yoilteller 설계도 훔쳐옴)
		Class clazz = Class.forName("com.fastcampus.ch2.YoilTellerMVC");
        	// 정보들을 이용해 YoilTeller의 객체를 생성 (설계도 사본으로 구현)
		Object obj = clazz.newInstance();
		
		// 2. YoilTeller의 모든 매소드 정보를 가져와서 배열에 저장 
		Method[] methodArr = clazz.getDeclaredMethods();
		
		// 매소드 하나씩 읽어서 그 정보를 출력 
		for(Method m : methodArr) {
			// 매소드의 이름
			String name = m.getName();
			
			// 매소드의 매개변수 목록
			Parameter[] paramArr = m.getParameters();
//			Class[] paramTypeArr = m.getParameterTypes();
			
			//매소드의 반환 타입
			Class returnType = m.getReturnType();
			
            // 매개변수의 타입과 이름을 일목요연하게 정리할 (  ,  ,  ) 형태의 빈 곽 생성
			//, 는 구분자, (는 접두사 )는 접미사
			StringJoiner paramList = new StringJoiner(", ", "(", ")");
			
			
			//for each문을 이용해 매개변수의 타입과 매개변수의 이름을 가져와서 joiner의 ()안에 넣는다. 
			// 예시 형태 (int year, int month, ...)
			for(Parameter param : paramArr) {
				String paramName = param.getName();
				Class  paramType = param.getType();
				
				paramList.add(paramType.getName() + " " + paramName);
			}
			
            //반환형, 함수이름, 매개변수 목록 순으로 출력
			System.out.printf("%s %s%s%n", returnType.getName(), name, paramList);
		}
	} // main
}

근데 이렇게 해도 매개 변수의 이름이 arg0 , arg1 이런 식으로 뜬다. 

왜냐하면 컴파일러는 매개 변수의 타입은 중요하게 생각하지만, 매개 변수의 이름은 중요하게 생각하지 않아서 저장 하지 않기 때문이다. 

 

컴파일러가 매개변수의 이름까지 기억하도록 만들려면 2가지 방법이 있다. 

(1) reflection API 이용

(2) Class File을 직접 읽는 방법 

 

(1) reflection API를 이용하는 방법은 다음과 같다. 

이는 java 1.8부터 추가된 기능이다. 

Window > Preference > Java > Compiler > store information about method parameters 선택 

이래도 안되는 경우가 있다 

이는 JRE System Library가 아직도 1.8 미만 버젼이어서 이다. 

이때는 pom.xml에 들어가서 properties의 자바 버젼을 1.8 이상 버젼으로 바꿔줘야 한다. 

plugin의 apache.mave.plugins 도 똑같이 버젼을 바꿔줘야한다. 

이때 바꿔주는 버젼은 위에서 들어간 Compiler의 버젼과 같아야 한다.

(2) 클래스 파일을 이용하는 방법도 있다. 

window  > show view > navigator 

여기서 target에 들어가면 모든 자바 클래스 마다 그 클래스의 정보가 저장된 클래스 파일이 있다. 

여기서 원하는 매소드가 담긴 클래스 파일에 가서 매개변수의 이름을 읽어오는 것이다. 

이 방법은 아직 어려워서 자세히 배우진 않았다. 

 

2. MVC의 원리 

class ModelController {
	public String main(HashMap map) {
		
		// 작업 결과를 맵에 저장 
		map.put("id", "asdf");
		map.put("pwd", "1111");
		
		return "txtView2"; // 뷰이름을 반환
	}
}

public class MethodCall {
	public static void main(String[] args) throws Exception{
		HashMap map = new HashMap();
		System.out.println("before:"+map);

		ModelController mc = new ModelController();
		String viewName = mc.main(map);
		
		System.out.println("after :"+map);
		
		render(map, viewName);
	}
	
	static void render(HashMap map, String viewName) throws IOException {
		String result = "";
		
		// 1. 뷰의 내용을 한줄씩 읽어서 하나의 문자열로 만든다.
		Scanner sc = new Scanner(new File(viewName+".txt"));
		
        //lineSeparator는 지금 쓰고 있는 OS의 개행문자를 나타낸다.
		while(sc.hasNextLine())
			result += sc.nextLine()+ System.lineSeparator();
		
		// 2. map에 담긴 key를 하나씩 읽어서 template의 ${key}를 value로 바꾼다.
		Iterator it = map.keySet().iterator();
		
		while(it.hasNext()) {
			String key = (String)it.next();

			// 3. replace()로 key를 value 치환한다.
            //.replace(A,B) A를 B로 바꾼다.
			result = result.replace("${"+key+"}", (String)map.get(key));
		}
		
		// 4.렌더링 결과를 출력한다.
		System.out.println(result);
	}
}

 

3. 스스로 해보기 

package com.fastcampus.ch2;

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.StringJoiner;

public class MethodInfo{
	
	public static void main (String[] args) throws Exception {
		
		Class clazz = Class.forName("com.fastcampus.ch2.YoilTeller");
		Object obj = clazz.newInstance();
		
		Method[] methodArr = clazz.getDeclaredMethods();
		
		for(Method m : methodArr) {
			String name = m.getName();
			Parameter[] paramArr = m.getParameters();
//			Class[] paramTypeArr = m.getParameterTypes();
			Class returnType = m.getReturnType();
			
			StringJoiner paramList = new StringJoiner(",", "(", ")");
			
			for(Parameter param : paramArr) {
				String paramName = param.getName();
				Class paramType = param.getType();
				
				paramList.add(paramType.getName() + " " + paramName);
			}
			
			System.out.printf("%s %s%s%n", returnType.getName(), name, paramList);
		}
		
	}
}
class ModelController {
	public String main(HashMap map) {
		
		// 작업 결과를 맵에 저장 
		map.put("id", "asdf");
		map.put("pwd", "1111");
		
		return "txtView2"; // 뷰이름을 반환
	}
}

public class MethodCall {
	public static void main(String[] args) throws Exception{
		HashMap map = new HashMap();
		System.out.println("before:" +map);
		
		ModelController mc = new ModelController();
		String viewName = mc.main(map);
		
		System.out.println("after :" + map);
		
		render(map, viewName);
	}


static void render(HashMap map, String viewName) throws IOException {
	String result = "";
	
	Scanner sc = new Scanner (new File(viewName + ".txt"));
	
	while (sc.hasNextLine()) {
		result += sc.nextLine() + System.lineSeparator();
	}
	
	Iterator it = map.keySet().iterator();
	
	while(it.hasNext()) {
		String key = (String)it.next();
		
		result = result.replace("${"+key+"}", (String)map.get(key));
	}
	
	System.out.println(result);
	
	
		}
	}