ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Spring] 003. AOP 의 개요
    SsY 2023. 6. 28. 14:04
    728x90
    AOP 개요
    ■■■ AOP(Aspect Oriented Programming) ■■■
    ※ 공통의 관심 사항을 적용해서 발생하는 의존 관계의 복잡성과
       코드 중복을 해소해주는 프로그래밍 기법.
    --------------------------------------------------------------------------------------------------------------
    ○ AOP 개념
       //-- 보조 업무가 주인공
       //-- 즉 aspect 라고 지칭하게 되면 보조업무를 의미한다.
       주 업무를 수행할 때 보조적인 업무(주 업무 실행 시간 체크, 로그 기록 등) 가 진행되어야 하는 상황이다.
       만약, 주 업무가 여러개이고, 동일한 보조 업무의 수행이 진행되어야 한다면,
       보조 업무 부분은 중복된 코드가 될 수 밖에 없다.
       이런 중복 요소를 제거하고, 보조 업무를 보다 독립적인 방법으로 실행할 수 있도록
       구성하는 것을 AOP 기법이라고 한다.
    --------------------------------------------------------------------------------------------------------------   
    ○ AOP 관련 주요 용어
       - **보조 업무(cross-cutting concern)**
         주 업무시 발생하는 보조적인 업무.
         주 업무와 분리 및 결합이 쉽게 이루어질 수 있도록 만들어야한다.
       
       - 주 업무(core concern)
         핵심적인 기능을 수행하는 부분.
         사용자의 요청에 대한 기본적인 수행 및 관련 결과를 반환해야한다.
      
       - Advice
         언제 어떤 공통 관심 기능(보조 업무, cross-cutting concern)을 적용할지 결정하는 방법
         //-- 어떤 위상에 삽입하는지
         Before Advice, After Advice, Around Advice 등이 있다.
         ·Before Advice
           보조 업무가 주 업무 실행 전에 수행되는 경우
         ·After Advice
           보조 업무가 주 업무 실행 후에 수행되는 경우
         ·Around Advice
           보조 업무가 주 업무 실행 전과 후에 수행되는 경우
       
       - proxy
         //-- 틀
         주 업무를 실행하는 객체와 동일한 모양을 가진 가짜 객체.
         사용자가 직접 주 업무를 실행하는 객체를 찾아가는 것이 아니라, 
         proxy 를 찾아가도록 지정하게 된다.
         proxy 내부에서 보조 업무를 실행한 후, 주 업무를 호출하도록 하면
         외부에서 볼 때 주 업무를 실행하는 것과 같은 결과가 나오도록 할 수 있다.
         
       - joinpoint
         proxy 내보에서 주 업무를 호출하는 경우에 특정 지점만 호출되도록 할 수 있다.
       
       - weaving
         advice 를 주 업무에 적용하는 과정을 부르는 명칭.
         
       - aspect
         여러 주 업무 객체에 공통적으로 적용되는 공통 관심 사항(보조업무)을 aspect 라고 한다.
    --------------------------------------------------------------------------------------------------------------
    ○ AOP 진행 순서
    
        사용자          프록시              보조업무               주업무
       (client)         (proxy)     (cross-cutting concern)    (core concern)
          ○-------------------------------------------------------->○
          ●------①----->●
                          ●--------②-------->●
                          ●-------------------③------------------->●
                          ●<------------------④--------------------●
                          ●---------⑤------->●
                          
          ○<--------------------------------------------------------○
          ●<-----⑥------●
          
       ① 사용자는 proxy 에 접근한다.
          사용자 입장에서는 proxy 객체가 주 업무(core concern) 객체인 것으로 인지하게 된다.
          
       ② proxy 객체 내부에서 보조 업무(cross-cutting concern)를 진행하게 된다.
          주 업무 실행 전에 수행되는 보조 업무는 Before Advice , Around Advice 가 있다.
          
       ③ proxy 객체 내부에서 주 업무(core concern)를 호출한다.
          주 업무가 수행된다
          
       ④ 주 업무가 수행된 결과 값을 반환한다.
       
       ⑤ proxy 객체 내부에서 보조 업무(cross-cutting concern)를 진행하게 된다.
          주 업무 실행 후에 수행되는 보조 업무는 After Advice, Around Advice 가 있다.
       
       ⑥ 사용자에게 결과값을 반환한다.

    SpringPrj05
    ■■■ AOP 개념 실습 01 (AOP 기법을 적용하기 전) ■■■
    ○ 실습 성격 및 주요 사항
    1. 콘솔프로젝트 → Java Project → SpringPrj05
    2. 기본적인 산술 연산처리                       
    3. AOP 기법을 사용하지 않은 상태로 보조 업무를 적용시켜보는 실습 진행
       ※ 보조 업무 → 시간 측정 및 로그 기록
    4. 로그 및 스톱워치 기능을 사용하기 위해 관련 jar 파일을 등록하여 실습을 진행할 수 있도록 한다.
    
    ○ 등록해야 할 jar 파일
    - 경로1 : C:\s-f-3.0.2-with-docs\dist
      ·파일1 :  org.springframework.core-3.0.2.RELEASE.jar     (core) //-- 스톱워치 
    - 경로2 : C:\s-f-3.0.2-dependencies\org.apache.commons\com.springsource.org.apache.commons.logging\1.1.1
      ·파일2 :  com.springsource.org.apache.commons.logging-1.1.1.jar //-- 로그기능
      
    ○ 물리적 파일 구성
    1. Calculator.java        → 인터페이스
    2. CalculatorImpl.java    → 클래스. 주 업무와 보조 업무 적용
    3. Main.java              → 클래스. main() 메소드를 포함하는 테스트 클래스

    주 업무 : 연산
    보조 업무 : 로그기록, 시간측정

    물리적파일 2,3 번만 구성해도 가능. 단, AOP 를 구현하기 위해서는 인터페이스 구성이 필요함.
    왜? IoC/ DI 적용이 된 상태로 AOP 를 적용해야하기 때문에.

    ++
    지금까지는 있는 포지션에서 반복적인 일을 하는 과정에서는 반복적 호출을 통해서 해결해 왔었기 때문에
    AOP 를 구성해서 처리하는 것에 마음이 와닿지는 않지만, 사실 이는 Enterprise 급 에서 사용하는 기법으로 AOP 를 이용하기 때문에 직접 체감하기가 힘들며, 용어를 통해서 소통을 많이 하는 편이다.
    ※ 용어 기억 ※

    • Calculator.java
    /*===================
       Calculator.java
       - 인터페이스
     ===================*/
    
    package com.test.spr;
    
    // ※ 스프링에서 AOP 기법을 적용하기 위해서는
    //    대상 객체가 인터페이스를 구현하고 있어야 한다.
    
    public interface Calculator
    {
    	// 주 업무(core concern) 진행을 위한 메소드 선언 → 추상 메소드
    	//-- 덧셈, 뺄셈, 곱셈, 나눗셈
    	public int add(int x, int y);
    	public int sub(int x, int y);
    	public int multi(int x, int y);
    	public int div(int x, int y);	//-- 실습 편의상 정수형 처리
    	//-- 가이드 라인 제시
    }

    • CalculatorImpl.java
      - 주 업무 처리 프로세스 작성 후 보조 업무 설정
      - AroundAdvice 유형
    /*===============================================
       CalculatorImpl.java
       - 클래스
       - Calculator 인터페이스를 구현하는 클래스
       - 주 업무와 보조 업무가 함께 처리되는 형태
    =============================================== */
    package com.test.spr;
    
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import org.springframework.util.StopWatch;
    
    public class CalculatorImpl implements Calculator
    {
    	// 주 업무(core concern) 진행을 위한 메소드 구현
    	
    	@Override
    	public int add(int x, int y)
    	{
    		int result = 0 ;
    		
    		// 보조 업무 (cross-cutting concern) 설정
    		//-- 시간 측정 및 로그 기록 작성
    		Log log = LogFactory.getLog(this.getClass());
    		//                          ---- CalculatorImpl을 의미
    		StopWatch sw = new StopWatch();
    		sw.start();
    		log.info("처리 시간 측정 시작 ---------------");	//-- 콘솔 창에 빨간색 글씨로 확인됨
    		
    		// 주 업무(core concern) 실행 내용
    		result = x + y;
    		
    		System.out.printf("%d + %d = %d%n", x, y, result);	//-- 콘솔 창에 검정색 글씨로 확인됨
    
    		sw.stop();
    		log.info("처리 시간 측정 종료 ---------------");
    		log.info(String.format("경과시간 : %s/1000초", sw.getTotalTimeMillis()));
    		
    		return result;
    	}
    
    	@Override
    	public int sub(int x, int y)
    	{
    		int result = 0 ;
    		
    		// 보조 업무 (cross-cutting concern) 설정
    		//-- 시간 측정 및 로그 기록 작성
    		Log log = LogFactory.getLog(this.getClass());
    		StopWatch sw = new StopWatch();
    		sw.start();
    		log.info("처리 시간 측정 시작 ---------------");
    		
    		// 주 업무(core concern) 실행 내용
    		result = x - y;
    		
    		System.out.printf("%d - %d = %d%n", x, y, result);
    		
    		sw.stop();
    		log.info("처리 시간 측정 종료 ---------------");
    		log.info(String.format("경과시간 : %s/1000초", sw.getTotalTimeMillis()));
    		
    		return result;
    	}
    
    	@Override
    	public int multi(int x, int y)
    	{
    		int result = 0 ;
    		
    		// 보조 업무 (cross-cutting concern) 설정
    		//-- 시간 측정 및 로그 기록 작성
    		Log log = LogFactory.getLog(this.getClass());
    		StopWatch sw = new StopWatch();
    		sw.start();
    		log.info("처리 시간 측정 시작 ---------------");
    
    		// 주 업무(core concern) 실행 내용
    		result = x * y;
    		
    		System.out.printf("%d * %d = %d%n", x, y, result);
    		
    		sw.stop();
    		log.info("처리 시간 측정 종료 ---------------");
    		log.info(String.format("경과시간 : %s/1000초", sw.getTotalTimeMillis()));
    		
    		return result;
    	}
    
    	@Override
    	public int div(int x, int y)
    	{
    		int result = 0 ;
    		
    		// 보조 업무 (cross-cutting concern) 설정
    		//-- 시간 측정 및 로그 기록 작성
    		Log log = LogFactory.getLog(this.getClass());
    		StopWatch sw = new StopWatch();
    		sw.start();
    		log.info("처리 시간 측정 시작 ---------------");
    		
    		// 주 업무(core concern) 실행 내용
    		result = x / y;
    		
    		System.out.printf("%d / %d = %d%n", x, y, result);
    		
    		sw.stop();
    		log.info("처리 시간 측정 종료 ---------------");
    		log.info(String.format("경과시간 : %s/1000초", sw.getTotalTimeMillis()));
    		
    		return result;
    	}
    	
    }

    ※ 각각의 업무에서 동일하게 반복되는 것을 호출로 처리 가능 + 반드시 인터페이스가 등장 할 필요가 없음
    → AOP 기법 적용을 위해서 인터페이스 필요
    → 보조업무를 외부 메소드가 동일하게 있고 주 업무만 바꿔쓸 수 도 있는 관점으로 보면
         보조 업무가 중심 틀이 되어 주 업무 메소드를 만들어 갈아끼우는 방식으로도 처리가 가능한 것!


    • Main.java
    /*=========================================
       Main.java
       - 클래스
       - main() 메소드가 포함된 테스트 클래스
    ===========================================*/
    package com.test.spr;
    
    public class Main
    {
    
    	public static void main(String[] args)
    	{
    		// 주 업무(core concern) 실행을 할 수 있는 객체 준비
    		// 인터페이스 변수 = new 인터페이스구현클래스();
    		// List list = new ArrayList();
    		Calculator cal = new CalculatorImpl();
    		
    		// 주 업무(core concern) 실행에 대한 테스트
    		int add = cal.add(10,20);
    		System.out.println(add);
    		
    		int sub = cal.sub(10,20);
    		System.out.println(sub);
    		
    		int multi = cal.multi(10, 20);
    		System.out.println(multi);
    		
    		int div = cal.div(10, 20);
    		System.out.println(div);
    	}
    
    }


    SpringPrj06
    ■■■ AOP 개념 실습 02 (AOP 기법을 적용, Spring AOP 기법X) ■■■
    ○ 실습 성격 및 주요 사항
    1. 콘솔프로젝트 → Java Project → SpringPrj06
    2. 기본적인 산술 연산처리                       
    3. AOP 기법을 사용하지 않은 상태로 보조 업무를 적용시켜보는 실습 진행
       ※ 보조 업무 → 시간 측정 및 로그 기록
    4. 로그 및 스톱워치 기능을 사용하기 위해 관련 jar 파일을 등록하여 실습을 진행할 수 있도록 한다.
    
    ○ 등록해야 할 jar 파일
    - 경로1 : C:\s-f-3.0.2-with-docs\dist
      ·파일1 :  org.springframework.core-3.0.2.RELEASE.jar     (core)  
    - 경로2 : C:\s-f-3.0.2-dependencies\org.apache.commons\com.springsource.org.apache.commons.logging\1.1.1
      ·파일2 :  com.springsource.org.apache.commons.logging-1.1.1.jar
      
    ○ 물리적 파일 구성
    1. Calculator.java        → 인터페이스 (기존 소스코드 그대로 활용)
    2. CalculatorProxy.java   → 프록시 클래스 (가짜 클래스)            //-- check!!!
                                 (보조 업무 적용 및 주 업무 호출 과정)
    3. CalculatorImpl.java    → 클래스. 주 업무만 적용                 //-- check
    4. Main.java              → 클래스. main() 메소드를 포함하는 테스트 클래스
    • Calculator.java : 01 번 실습과 동일

    • CalculatorProxy.java
    /*=======================================
       CalculatorProxy.java
       - 프록시 클래스
       - 보조 업무 적용 및 주 업무 호출 과정
    ========================================*/
    
    // ※ Proxy 클래스를 만드는 여러 가지 방법들 중 비교적 쉽고 직관적인 방법은
    //    InvocationHandler 인터페이스를 구현하는 클래스를 만드는 것이다.
    
    package com.test.spr;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import org.springframework.util.StopWatch;
    
    public class CalculatorProxy implements InvocationHandler
    {
    	// 주요 속성 구성
    	
    	// target → (proxy 내부에서)가짜가...진짜 행세를 하게 될 대상
    	private Object target;
    	
    	// 생성자 정의
    	public CalculatorProxy(Object target)
    	{
    		this.target = target;
    	}
    
    	// InvocationHandler 인터페이스의 메소드 재정의
    	// -- 보조 업무 적용 및 주 업무 호출 과정 추가
    	@Override
    	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
    	{
    		// 보조 업무 (cross-cutting concern) 설정
    		//-- 시간 측정 및 로그 기록
    		Log log = LogFactory.getLog(this.getClass());	//-- 시작할 때는 공장부터 짓자~
    		StopWatch sw = new StopWatch();
    		sw.start();
    		log.info("처리 시간 측정 시작 ---------------");
    		
    		// 주 업무(core concern) 실행 내용
    		Object result = method.invoke(target, args);
    		//                                    ---- 여러가지 속성들
    		
    		sw.stop();
    		log.info("처리 시간 측정 종료 ---------------");
    		log.info(String.format("경과시간 : %s/1000초", sw.getTotalTimeMillis()));
    		
    		return result;
    	}
    }

    • CalculatorImpl.java
    /*=============================================
       CalculatorImpl.java
       - 클래스
       - Calculator 인터페이스를 구현하는 클래스
       - 주 업무만 적용된 형태로 구성
    ============================================= */
    package com.test.spr;
    
    public class CalculatorImpl implements Calculator
    {
    	// 주 업무(core concern) 진행을 위한 메소드 구현
    
    	@Override
    	public int add(int x, int y)
    	{
    		int result = 0;
    		
    		result = x + y;
    		System.out.printf("%d + %d = %d%n", x, y, result);
    		
    		return result;
    	}
    
    	@Override
    	public int sub(int x, int y)
    	{
    		int result = 0;
    		
    		result = x - y;
    		System.out.printf("%d - %d = %d%n", x, y, result);
    		
    		return result;
    	}
    
    	@Override
    	public int multi(int x, int y)
    	{
    		int result = 0;
    		
    		result = x * y;
    		System.out.printf("%d * %d = %d%n", x, y, result);
    		
    		return result;
    	}
    
    	@Override
    	public int div(int x, int y)
    	{
    		int result = 0;
    		
    		result = x / y;
    		System.out.printf("%d / %d = %d%n", x, y, result);
    		
    		return result;
    	}
    }

    • Main.java
      - Proxy 를 직접 생성 함
      - Calculator proxy = (Calculator)Proxy.newProxyInstance(주업무정보, 주업무인터페이스정보, 보조업무수행객체);
                                                                  -------------------------(내가 작성하지 않은 메소드)
        별도로 설계도를 만들지 않고 정적 메소드를 통해서 main() 에서 생성했다는 의미
    /*=========================================
       Main.java
       - 클래스
       - main() 메소드가 포함된 테스트 클래스
    ===========================================*/
    package com.test.spr;
    
    import java.lang.reflect.Proxy;
    
    public class Main
    {
    
    	public static void main(String[] args)
    	{
    		// 주 업무(core concern) 실행을 할 수 있는 객체 준비
    		// 인터페이스 변수 = new 인터페이스구현클래스();
    		// List list = new ArrayList();
    		Calculator cal = new CalculatorImpl();
    		
    		// 주 업무(core concern) 실행에 대한 테스트 → AOP 기법 적용 전
    		/*
    		int add = cal.add(10,20);
    		System.out.println(add);
    		
    		int sub = cal.sub(10,20);
    		System.out.println(sub);
    		
    		int multi = cal.multi(10, 20);
    		System.out.println(multi);
    		
    		int div = cal.div(10, 20);
    		System.out.println(div);
    		*/
    
    		// 주 업무(core concern) 실행에 대한 테스트 → AOP 기법 적용 후
    		//-- static 메소드 newProxyInstance()
    		//-- proxy 기반으로 새로운 proxy 라는 인스턴스를 만들어 내는 것 (007 상자 툴킷...)
    		//-- 진짜 행세를 하기 위해서 대상과 그 대상에게 속성을 물려준 인터페이스들의 정보를 요구
    		//-- 오브젝트 타입 다운캐스팅
    		Calculator proxy = (Calculator)Proxy.newProxyInstance(
    				cal.getClass().getClassLoader()		// 주 업무 실행 클래스에 대한 정보 전달(제공)
    			//  ---/----------/----------------
    			//주 업무 객체(대상) / 설계도 / 클래스를 읽어오는 스캐너
    				, cal.getClass().getInterfaces()	// 주 업무 실행 클래스의 인터페이스들에 대한 정보 전달(제공) 
    				//---/----------/---------------
    				//주 업무 객체(대상) / 설계도 / 클래스가 implements 하고있는 인터페이스(들) 정보를 읽어오는 스캐너
    				, new CalculatorProxy(cal));		// 보조 업무 실행 클래스에 대한 정보 전달(제공)
    		        //-- 가짜 (틀) 을 가져와서 결합시키는 과정
    		
    		int add = proxy.add(10, 20);
    		System.out.println(add);
    		
    		int sub = proxy.sub(10, 20);
    		System.out.println(sub);
    		
    		int multi = proxy.multi(10, 20);
    		System.out.println(multi);
    		
    		int div = proxy.div(10, 20);
    		System.out.println(div);
    		
    	}// end main()
    
    }

    SpringPrj07
    ■■■ AOP 개념 실습 03 (Spring AOP 기법) ■■■
    ○ 실습 성격 및 주요 사항
    1. 콘솔프로젝트 → Java Project → SpringPrj07
    2. 기본적인 산술 연산처리                       
    3. AOP 기법을 사용한 상태로 보조 업무를 적용시켜보는 실습 진행
       ※ 보조 업무 → 시간 측정 및 로그 기록
    4. 로그 및 스톱워치 기능을 사용하기 위해 관련 jar 파일을 등록하여 실습을 진행할 수 있도록 한다.
    
    ○ 등록해야 할 jar 파일
       (로그 기록 및 스톱워치 사용을 위해 등록한 jar 파일)
       + 스프링 AOP 기법을 적용하기 위한 jar 파일
    - 경로1 : C:\s-f-3.0.2-with-docs\dist
      ·파일1 :  org.springframework.asm-3.0.2.RELEASE.jar           (asm)
      ·파일2 :  org.springframework.beans-3.0.2.RELEASE.jar         (beans)
      ·파일3 :  org.springframework.context-3.0.2.RELEASE.jar       (context)
      ·파일4 :  org.springframework.core-3.0.2.RELEASE.jar          (core)
      ·파일5 :  org.springframework.expression-3.0.2.RELEASE.jar    (expression)
      ·파일6 :  org.springframework.aop-3.0.2.RELEASE.jar           (aop)
    - 경로2 : C:\s-f-3.0.2-dependencies\org.apache.commons\com.springsource.org.apache.commons.logging\1.1.1
      ·파일7 :  com.springsource.org.apache.commons.logging-1.1.1.jar
    - 경로3 : C:\s-f-3.0.2-dependencies\org.aopalliance\com.springsource.org.aopalliance\1.0.0
      ·파일8 :  com.springsource.org.aopalliance-1.0.0.jar
      
    ○ 물리적 파일 구성
    1. Calculator.java        → 인터페이스 (기존 소스코드 그대로 활용)
    2. CalculatorAspect.java  → 보조 업무 클래스 
                                 보조 업무 적용 및 주 업무 호출 과정
    3. CalculatorImpl.java    → 클래스. 주 업무만 적용 (기존 소스코드 그대로 활용)
    4. Main.java              → 클래스. main() 메소드를 포함하는 테스트 클래스
    5. config.xml             → 스프링 환경 설정 파일
                                 객체 생성 및 DI 설정
                                 (applicationContext.xml 과 동일하나 이름만 바꿔 사용해봄)
    • Calculator.java (02번 실습과 동일)

    • CalculatorAspect.java
      - Proxy 의 역할
    /*====================================
       CalculatorAspect.java
       - 보조 업무 수행 클래스
       - 보조 업무 적용 및 주 업무 호출
    ==================================== */
    
    // ※ Spring AOP Proxy 클래스를 만들기 위해서
    //    MethodInterceptor 인터페이스를 구현하는 클래스로 설계한다.
    
    package com.test.spr;
    
    import org.aopalliance.intercept.MethodInterceptor;
    import org.aopalliance.intercept.MethodInvocation;
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import org.springframework.util.StopWatch;
    
    public class CalculatorAspect implements MethodInterceptor
    {
    	// 보조 업무 적용 및  주 업무 호출 과정 추가
    	@Override
    	public Object invoke(MethodInvocation method) throws Throwable
    	{
    		// 보조 업무(cross-cutting concern) 설정
    		//-- 시간 측정 및 로그 기록
    		Log log = LogFactory.getLog(this.getClass());
    		StopWatch sw = new StopWatch();
    		sw.start();
    		log.info("처리 시간 측정 시작 -------------");
    		
    		// 주 업무(core concern) 호출 부분
    		Object result = method.proceed();
    		
    		sw.stop();
    		log.info("처리 시간 측정 종료 -------------");
    		log.info(String.format("경과 시간 : %s/1000초", sw.getTotalTimeMillis()));
    		
    		return result;
    	}
    	
    	
    }// end Class

    • CalculatorImpl.java  (02번 실습과 동일)

    • Main.java
    /*=========================================
       Main.java
       - 클래스
       - main() 메소드가 포함된 테스트 클래스
    ===========================================*/
    package com.test.spr;
    
    //import java.lang.reflect.Proxy;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    
    public class Main
    {
    
    	public static void main(String[] args)
    	{
    		// 주 업무(core concern) 실행을 할 수 있는 객체 준비
    		// 인터페이스 변수 = new 인터페이스구현클래스();
    		// List list = new ArrayList();
    		//Calculator cal = new CalculatorImpl();
    		
    		// 주 업무(core concern) 실행에 대한 테스트 → AOP 기법 적용 전
    		/*
    		int add = cal.add(10,20);
    		System.out.println(add);
    		
    		int sub = cal.sub(10,20);
    		System.out.println(sub);
    		
    		int multi = cal.multi(10, 20);
    		System.out.println(multi);
    		
    		int div = cal.div(10, 20);
    		System.out.println(div);
    		*/
    
    		// 주 업무(core concern) 실행에 대한 테스트 → AOP 기법 적용 후
    		//-- static 메소드 newProxyInstance()
    		//-- proxy 기반으로 새로운 proxy 라는 인스턴스를 만들어 내는 것 (007 상자 툴킷...)
    		//-- 진짜 행세를 하기 위해서 대상과 그 대상에게 속성을 물려준 인터페이스들의 정보를 요구
    		//-- 오브젝트 타입 다운캐스팅
    		/*
    		Calculator proxy = (Calculator)Proxy.newProxyInstance(
    				cal.getClass().getClassLoader()		// 주 업무 실행 클래스에 대한 정보 전달(제공)
    			//  ---/----------/----------------
    			//주 업무 객체(대상) / 설계도 / 클래스를 읽어오는 스캐너
    				, cal.getClass().getInterfaces()	// 주 업무 실행 클래스의 인터페이스들에 대한 정보 전달(제공) 
    				//---/----------/---------------
    				//주 업무 객체(대상) / 설계도 / 클래스가 implements 하고있는 인터페이스(들) 정보를 읽어오는 스캐너
    				, new CalculatorProxy(cal));		// 보조 업무 실행 클래스에 대한 정보 전달(제공)
    		        //-- 가짜 (틀) 을 가져와서 결합시키는 과정
    		
    		int add = proxy.add(10, 20);
    		System.out.println(add);
    		
    		int sub = proxy.sub(10, 20);
    		System.out.println(sub);
    		
    		int multi = proxy.multi(10, 20);
    		System.out.println(multi);
    		
    		int div = proxy.div(10, 20);
    		System.out.println(div);
    		*/
    		
    		// 주 업무(core concern) 실행에 대한 테스트 → Spring AOP 기법을 적용한 후~!!!
    	    ApplicationContext context = new ClassPathXmlApplicationContext("config.xml");
    	    
    	    //Calculator cal = new CalculatorImpl();
    	    //Calculator cal = (Calculator)객체수신;
    	    //Calculator cal = (Calculator)context.getBean("proxy");
    	    Calculator cal = context.getBean("proxy", Calculator.class);
    	    
    	    
    	    int add = cal.add(10, 20);
    	    System.out.println(add);
    	    
    	    int sub = cal.sub(10, 20);
    	    System.out.println(sub);
    	    
    	    int multi = cal.multi(10, 20);
    	    System.out.println(multi);
    	    
    	    int div = cal.div(10, 20);
    	    System.out.println(div);
    	   }
    
    		
    	}// end main()

    • config.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
               http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
    
    	<!--
    		※ 스프링이 제공하는 환경 설정 XML 파일 샘플
    		   → 스프링이 생성하고 관리해야 할 객체들에 대한 정보 전달
    	-->
    	
    	<!-- CalculatorImpl 클래스의 객체 생성 및 관리를 위한 정보 전달 -->
    	<bean id="cal" class="com.test.spr.CalculatorImpl"></bean>
    	
    	<!-- CalculatorAspect 클래스의 객체 생성 및 관리를 위한 정보 전달 -->
    	<bean id="aspect" class="com.test.spr.CalculatorAspect"></bean>
    	
    	<!-- CHECK!!!!! -->
    	<!-- 스프링이 제공하는 가짜 객체(Proxy) 클래스의 객체 생성 및 관리를 위한 정보 전달 -->
    	<!-- → 『ProxyFactoryBean』 -->
    	<!-- 다른 메소드에서 위 이름으로 인텔리전스 기능 이용하여 import 주소 가져와서 class 에 붙여넣기 -->
    	<bean id="proxy" class="org.springframework.aop.framework.ProxyFactoryBean">
    	
    		<!-- 주 업무 클래스의 인터페이스 정보 제공 -->
    		<!-- 『proxyInterfaces』 -->
    		<property name="proxyInterfaces">
    			<list>
    				<value>com.test.spr.Calculator</value>
    				<!-- 여러개로 구성할 때 
    				<value>com.test.spr.Calculator</value>
    				<value>com.test.spr.Calculator</value>
    				-->
    			</list>
    		</property>
    		
    		<!-- 주 업무 클래스의 객체 정보 제공 -->
    		<!-- 『target』 -->
    		<!-- 위에서 만든 인스턴스의 정보를 참조하게 끔 설정해줌 -->
    		<property name="target" ref="cal"></property>
    		
    		<!-- 보조 업무 클래스의 객체 정보 제공 -->
    		<!-- 『interceptorNames』 -->
    		<property name="interceptorNames">
    			<list>
    				<!-- 위에서 이미 구성해 둔 aspect 값으로 구성 -->
    				<value>aspect</value>
    			</list>
    		</property>
    	</bean>
    
    </beans>

     

    728x90
Designed by planet-si