Spring #20 AOP 자바 구현

underlier12·2020년 2월 12일
0

SPRING

목록 보기
20/25

20. AOP 자바 구현

순수 자바로 AOP 구현하기

이론에 맞춰 AOP를 자바 코드로만 구현해본다. 다음과 같이 패키지와 클래스를 생성하고

entity 패키지도 복사해오면서 aop로만 변경해준다. 이 때 Annotation은 제거했고 메소드들을 result를 거쳐 반환할 수 있도록 수정했다.

NewlecExam.java

먼저 AOP 개념이 적용되지 않는다면 메소드 내에 주석처리 된 부분이 그대로 들어가 있을 것이다. 이제 Cross-cutting Concern을 분리해 연결해본다.

package spring.aop.entity;

public class NewlecExam implements Exam {

	private int kor;
	private int eng;
	private int math;
	private int com;
	
	public NewlecExam() {
		// TODO Auto-generated constructor stub
	}
	
	public NewlecExam(int kor, int eng, int math, int com) {
		super();
		this.kor = kor;
		this.eng = eng;
		this.math = math;
		this.com = com;
	}
	
	public int getKor() {
		return kor;
	}

	public void setKor(int kor) {
		this.kor = kor;
	}

	public int getEng() {
		return eng;
	}

	public void setEng(int eng) {
		this.eng = eng;
	}

	public int getMath() {
		return math;
	}

	public void setMath(int math) {
		this.math = math;
	}

	public int getCom() {
		return com;
	}

	public void setCom(int com) {
		this.com = com;
	}

	@Override
	public int total() {
		
//		long start = System.currentTimeMillis();
		
		int result = kor+eng+math+com; 
		
		try {
			Thread.sleep(200);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
//		
//		long end = System.currentTimeMillis();
//		
//		String message = (end - start) + "ms 소요 ";
//		System.out.println(message);
		
		return result;
	}

	@Override
	public float avg() {
		
		float result = total()/4.0f; 
		
		return result;
	}

	@Override
	public String toString() {
		return "NewlecExam [kor=" + kor + ", eng=" + eng + ", math=" + math + ", com=" + com + "]";
	}

}

Program.java

다음과 같이 프락시를 통해 연결이 된 모습을 볼 수 있다. 프락시 객체는 새 인스턴스를 만들 때 Core Concern의 클래스로더와 인터페이스들의 클래스, InvocationHandler를 필요로 한다. 아래는 익명 InvocationHandler를 생성한 것이며 invoke 메소드에서 부 업무 로직이 차지한 것을 알 수 있다. 대신 그 사이 어디서 Core Concern에 접근할지를 알려주는 result가 method.invoke를 통해 실행될 것임을 암시한다.

package spring.aop;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import spring.aop.entity.Exam;
import spring.aop.entity.NewlecExam;

public class Program {

	public static void main(String[] args) {
		
		Exam exam = new NewlecExam(1, 1, 1, 1);
		
		Exam proxy = (Exam) Proxy.newProxyInstance(NewlecExam.class.getClassLoader(), 
				new Class[] {Exam.class}, 
				new InvocationHandler() {
					
					@Override
					public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
						
						long start = System.currentTimeMillis();
						
						Object result = method.invoke(exam, args);
						
						long end = System.currentTimeMillis();
						
						String message = (end - start) + "ms 소요 ";
						System.out.println(message);
						
						return result;
					}
				});
		
		System.out.println("total is " + proxy.total());
		System.out.println("avg is " + proxy.avg());

	}

}

생성된 프락시 인스턴스는 Object 타입이기 떄문에 이를 형변환해서 사용한다

profile
logos and alogos

0개의 댓글