2020년 10월 6일 화요일

스프링 AOP 포인트컷(pointcut), StaticMethodMatcherPointcut 이론및실습, Spring AOP 용어 프록시/포인트컷/타겟클래스/위빙(자바동영상/스프링동영상/자바동영상/자바교육/스프링교육/SpringFramework/스프링프레임워크/스프링학원/자바학원/자바/JAVA)

 


스프링 AOP 포인트컷(pointcut), StaticMethodMatcherPointcut 이론및실습, Spring AOP 용어 프록시/포인트컷/타겟클래스/위빙(자바동영상/스프링동영상/자바동영상/자바교육/스프링교육/SpringFramework/스프링프레임워크/스프링학원/자바학원/자바/JAVA)  

 

3-5. 포인트컷(Pointcut)

 

n  Pointcut은 모든 Join Point Advice Weaving 되어야 할 Join Point의 집합을 정의한 것이다.

n  교차점(PointCut)은 특정한 클래스의 특정한 메소드가 특정한 기준과 일치하는지를 판단한다만약 그 메소드가 실제로 일치한다면 충고가 적용된다.

n  스프링은 충고를 받으려고 하는 클래스와 메소드의 관점에서 교차점을 정의하며 충고는 클래스의 이름과 메소드 시그네처(Method Signature)와 같은 특징에 기초하여 대상 클래스와 메소드에 엮인다.

n  스프링의 교차점 프레임워크를 위한 핵심 인터페이스는 PointCut, PointCut은 메소드와 클래스에 기초하여 충고를 어디에 엮을지 결정한다.

n  Pointcut 구현체를 사용하려면 먼저 Advisor 인터페이스의 인스턴스를 생성하거나 좀 더 구체적으로 PointcutAdvisor 인터페이스의 인스턴스를 생성해야 한다.

3393c5872db48cc884691855d03e4c79_1602027
3393c5872db48cc884691855d03e4c79_1602027
 

 

 

 

n  ControlFlowPointcut : 특정 메소드 하위의 모든 메소드 호출 또는 특정 클래스 하위의 모든 메소드 호출에 사용한다.

 

n  PointCut Interface

public interface PointCut {

   ClassFilter getClassFilter();   //클래스에 pointcut적용여부판단

   MethodMatcher getMethodMatcher(); //클래스의 특정메소드에 pointcut적용여부판단

}

 

n  ClassFilter Interface : 인자로 넘어온 Class가 충고를 받아야 하는지를 판단해야 한다.

public interface ClassFilter {

   boolean matches(Class class);

}

 

n  MethodMatcher

public interface MethodMatcher {

  public boolean matches(Method m, Class targetClass);

  public boolean isRuntime();

  public boolean matches(Method m, Class target, Object[] args);

}

matches(Method ,Class) 메소드는 대상 Class Method를 기초로 메소드가 충고를 받을 수 있는지의 여부를 판단한다. true가 리턴되면 어떤 유형의 MethodMatcher인지 판단하기 위해 isRuntime()이 호출된다정적 교차점(Static Pointcut)은 항상 실행되는 교차점을 정의하며 이 경우 isRuntime() false return 한다.

 

동적 교차점(Dynamic Pointcut)은 런타임시의 메소드 인자를 확인하여 충고가 실행되어야 하는지를 결정한다. matches 메소드와 마찬가지로 isRuntime()은 프록시 객체가 생성될 때 오직 한번만 호출된다.

 

n  충고자(Advisor)

Aspect는 행동을 정의한 충고와 실행돼야 할 위치를 정의한 교차점(Pointcut)의 조합으로 이루어 진다스프링에서는 이를 위해 충고자(Advisor)라는 것을 제공한다충고자는 충고(Advice)와 교차점(Pointcut)을 하나의 객체로 합친것 이다.

 

public interface PointcutAdvisor {

   Pointcut getPointcut();

   Advice getAdvice();

}

 

3-5-1. 포인트컷(Pointcut) - StaticMethodMatcherPointCut

 

n  StaticMethodMatcherPointcut을 상속할 때는 matches 메소드만 구현하면 되지만 올바른 타입의 메소드만 어드바이스가 적용되도록 할려면 getClassFilter() 메소드를 오버라이드 하는 것이 좋다.

 

File -> New -> Spring Legacy Project

Project name : springonj

Simple Spring Maven 선택

 

[First.java]

package onj.edu.aop1;

 

public class First {

           public void one() {

                      System.out.println("First One...");

           }

           public void two() {

                      System.out.println("First Two...");

           }

}

 

[Second.java]

package onj.edu.aop1;

 

public class Second {

           public void one() {

                      System.out.println("Second One...");

           }

           public void two() {

                      System.out.println("Second Two...");

           }

}

 

[SimpleAdvice.java]

package onj.edu.aop1;

 

import org.aopalliance.intercept.MethodInterceptor;

import org.aopalliance.intercept.MethodInvocation;

 

public class SimpleAdvice implements MethodInterceptor {

   public Object invoke(MethodInvocation invocation) throws Throwable {

           System.out.println(invocation.getMethod().getName());

 

           Object o = invocation.proceed();

           System.out.println("... SimpleAdvice의 충고가 적용됨 ...");

 

           return o;

   }

}

 

[SimpleStaticPointcut.java]

package onj.edu.aop1;

import java.lang.reflect.Method;

import org.springframework.aop.support.StaticMethodMatcherPointcut;

 

public class SimpleStaticPointcut extends StaticMethodMatcherPointcut {

// 아래는First.class의 one()의 실행 전/후 충고가 적용된다.

           public boolean matches(Method method, Class<?> cls) {

                      return ("one".equals(method.getName()) && cls == First.class);

           }

}

 

[StaticPointcutExam.java]

public class StaticPointcutExam {

public static void main(String[] args) {

First f = new First();

Second s = new Second();

First proxyFirst;

Second proxySecond;

 

//pointcut, advice 생성

Pointcut pc = new SimpleStaticPointcut();

Advice advice = new SimpleAdvice();

 

//advisor 생성(advice + pointcut)

Advisor advisor = new DefaultPointcutAdvisor(pc, advice);

 

//First 프록시 생성

ProxyFactory pf = new ProxyFactory();

pf.addAdvisor(advisor);

pf.setTarget(f);  //First.class를 타겟으로

proxyFirst = (First)pf.getProxy();

 

proxyFirst.one();

proxyFirst.two();

 

//Second 프록시 생성

pf = new ProxyFactory();

pf.addAdvisor(advisor);

pf.setTarget(s);  //Second.class를 타겟으로

proxySecond = (Second)pf.getProxy();

 

proxySecond.one();

proxySecond.two();

}

}

 

[결과]

one

First One...

... SimpleAdvice의 충고가 적용됨 ...

First Two...

Second One...

Second Two...

 

3393c5872db48cc884691855d03e4c79_1602027
 

 

이전에 작성한 프로그래밍적 방법을 통한 SmallMart AOP 예제에 getProducts2() 메소드를 추가로 만들고 StaticMethodMatcherPointcut을 적용하여 getProducts2 메소드에만 충고가 적용되도록 변경하자.

 

 

File , New , Spring Starter Project

ProjectName : demo-smallmart-1

 

1. SmallMart.java

 

package onj.hello.aop;

 

public interface SmallMart {

           public String getProducts(String productName) throws Exception ;

           public String getProducts2(String productName) throws Exception ;

}

 

 

 

2. SmallMartImpl.java

 

package onj.hello.aop;

 

public class SmallMartImpl implements SmallMart{

           public String getProducts(String productName) throws Exception {

                      System.out.println("getProduct()…" + productName);

                      //throw new Exception("예외 발생 시킴...");

                      return "SmallMart  getProducts......................";

           }

          

           public String getProducts2(String productName) throws Exception {

                      System.out.println("getProduct2()…" + productName);

                      //throw new Exception("예외 발생 시킴...");

                      return "SmallMart  getProducts2().....................";

           }

}

 

 

 

 

 

 

 

3. 이번에는 충고 클래스를 각각 만들자.

 

 

package oraclejava.traing.aop2;

 

import java.lang.reflect.Method;

 

import org.springframework.aop.AfterReturningAdvice;

 

public class AfterLoggingAdvice implements AfterReturningAdvice{

           public void afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3) throws Throwable{

                      System.out.println(arg1.getName() + " : 사후충고");

           }

}

 

 

 

 

 

package oraclejava.traing.aop2;

 

import org.aopalliance.intercept.MethodInterceptor;

import org.aopalliance.intercept.MethodInvocation;

 

public class AroundLoggingAdvice implements MethodInterceptor {

           public Object invoke(MethodInvocation arg0) throws Throwable {

                      String findName = (String) arg0.getArguments()[0];

                      if (findName == null) {

                                 throw new Throwable("예외");

                      }

                      System.out.println("[주변충고]메소드실행전..");

                      Object returnedObj = arg0.proceed();

                      System.out.println("[주변충고]메소드실행후");

                      //주변충고는 원래 메소드의 리컨값을 대체할 수 있다.

                      return "[주변충고]getProducts2() 메소드의 리턴을 대체 한것입니다.";

           }// :

}

 

 

 

 

package oraclejava.traing.aop2;

 

import java.lang.reflect.Method;

import org.springframework.aop.MethodBeforeAdvice;

 

public class BeforeLoggingAdvice implements MethodBeforeAdvice{

           public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable{//대상메소드의첫번째인자를캐스팅(String productName) …

                      String findName= (String)arg1[0];

                      System.out.println(arg0.getName() + ":: 사전충고.");

           }

}

 

 

 

 

 

package oraclejava.traing.aop2;

 

import org.springframework.aop.ThrowsAdvice;

 

public class ThrowsLoggingAdvice implements ThrowsAdvice{

           public void afterThrowing(Throwable throwable) {

                      System.out.println("예외충고 ....");

           }

}

 

 

4. 이번에는 포인트컷을 만들자. StaticMethodMatcherPointcut은 클래스이름 or 메소드 이름과 같은 정적인 정보에 기초하여 출고를 받을 메소드를 정의하는 포인트컷이며 스프링에서 제공한다이를 상속받아 포인트컷 클래스를 작성하자.

 

SmallMart클래스의 getProducts2 메소드가 충고를 받을 메소드 이다.

 

package oraclejava.traing.aop2;

 

import java.lang.reflect.Method;

 

import org.springframework.aop.ClassFilter;

import org.springframework.aop.support.StaticMethodMatcherPointcut;

 

public class SmallMartStaticPointcut extends StaticMethodMatcherPointcut{

           public boolean matches(Method method, Class<?> cls) {

                      return ("getProducts2".equals(method.getName()));

           }

      //아래처럼 getClassFilter를 만들어도 되지만 위 matches return문에 clas파라미터를

     //이용하여 같이 클래스 이름도 비교하면 더 간단해 진다.

     //return ("getProducts2".equals(method.getName() && clas == SmallMartImpl.class));

           public ClassFilter getClassFilter() {

                      return new ClassFilter() {

                                 public boolean matches(Class<?> cls) {

                                             return(cls== SmallMartImpl.class);}};}

}

 

 

 

5. 메인클래스

 

 

package onj.hello.aop;

 

import org.aopalliance.aop.Advice;

import org.springframework.aop.Advisor;

import org.springframework.aop.Pointcut;

import org.springframework.aop.framework.ProxyFactory;

import org.springframework.aop.support.DefaultPointcutAdvisor;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

 

@SpringBootApplication

public class DemoSmallmart1Application {

 

           public static void main(String[] args) {

                      SpringApplication.run(DemoSmallmart1Application.class, args);

                     

                      SmallMart target = new SmallMartImpl();

                     

                      Pointcut pc = new SmallMartStaticPointcut();

                      Advice advice1= new AfterLoggingAdvice();

                      Advisor advisor1= new DefaultPointcutAdvisor(pc, advice1);

                     

                      Advice advice2= new BeforeLoggingAdvice();

                      Advisor advisor2= new DefaultPointcutAdvisor(pc, advice2);

                     

                      Advice advice3= new AroundLoggingAdvice();

                      Advisor advisor3= new DefaultPointcutAdvisor(pc, advice3);

                     

                      Advice advice4= new ThrowsLoggingAdvice();

                      Advisor advisor4= new DefaultPointcutAdvisor(pc, advice4);

                     

                      ProxyFactory pf = new ProxyFactory();

                                            

                      pf.addAdvisor(advisor1);

                      pf.addAdvisor(advisor2);

                      pf.addAdvisor(advisor3);

                      pf.addAdvisor(advisor4);

                     

                      pf.setTarget(target);

                     

                      try {

                                 SmallMart proxy = (SmallMart) pf.getProxy();

                                 System.out.println(proxy.getProducts("오라클자바커뮤니티"));

                                 System.out.println(proxy.getProducts2("오라클자바커뮤니티"));

                      } catch (Exception e) {

                                 e.printStackTrace(System.out);

                      }

           }

 

}

 

 

 

 

#스프링충고, #포인트컷, #스프링pointcut, #스프링AOP, #스프링advice, #SpringAOP, #스프링DI, #스프링IoC, #SpringDI, #SpringIoC, #자바스프링, #Spring동영상, #Spring강의, #스프링프레임워크, #스프링교육, #스프링학원, #스프링강좌, #스프링강의, #자바학원, #자바, #스프링동영상, #자바동영상, #스프링프레임워크교육, #스프링프레임워크강의, #스프링프레임워크학원   

2020년 10월 5일 월요일

스프링 AOP 충고(Advice) 이론및 실습, Spring AOP 용어 프록시/포인트컷/타겟클래스/위빙(자바동영상/스프링동영상/자바동영상/자바교육/스프링교육/SpringFramework/스프링프레임워크/스프링학원/자바학원/자바/JAVA)

 스프링 AOP 충고(Advice) 이론및 실습, Spring AOP 용어 프록시/포인트컷/타겟클래스/위빙(자바동영상/스프링동영상/자바동영상/자바교육/스프링교육/SpringFramework/스프링프레임워크/스프링학원/자바학원/자바/JAVA)

 


ojc.asia/bbs/board.php?bo_table=LecSpring&wr_id=867

스프링 AOP 충고(Advice) 이론및 실습, Spring AOP 용어 프록시/포인트컷/타겟클래스/위빙(자바동영상/�

스프링 AOP 충고(Advice) 이론및 실습, Spring AOP 용어 프록시/포인트컷/타겟클래스/위빙(자바동영상/스프링동영상/자바동영상/자바교육/스프링교육/SpringFramework/스프링프레임워크/스프링학원/자바��

ojc.asia

https://youtu.be/e-ommLHoaOA

불러오는 중입니다...


Spring AOP 충고(Advice)


 

스프링 AOP에서 충고(Advice)는 어떤 메소드가 실행하기전에 가로채서 실행전 후로 어떠한 기능을 심어 놓는 것으로 횡단관심사(전체 프로젝트에 걸쳐저 있는 기능, 로깅, 로그인여부검사, 트랜잭션처리등) 기능을 구현한 것인데 다음과 같이 분류한다.



 

 

 


Aroud Advice의 앞단 처리 부분과 Before Advice, Aroud Advice의 뒷단 처리부분과 AfterReturning Advice간 실행순서는 정해져 있지 않고 먼저 추가되는 Advice, Advisor가 먼저 실행된다.


 

프로그래밍적인 방법을 통한 AOP 충고(Advice) 구현(ProxyFactory 이용)


 

프로그래밍적인 방법을 통해 Spring AOP 충고의 기본원리를 이해하자.

 

 


STS에서


 

1. File -> New -> (Spring Boot)Spring Starter Project



 

Next 클릭

 

Name : demo-smallmart

Type  : MAVEN

Package : onj.hello.aop


 

 

Next 클릭 , Finish  클릭

 

 

[SmallMart.java]


package onj.hello.aop;

 

public interface SmallMart {

           public void getProducts(String productName) throws Exception;

}

 

[SmallMartImpl.java]


package onj.hello.aop;

 

public class SmallMartImpl implements SmallMart {

           public void getProducts(String productName) throws Exception {

              System.out.println("[Target Method]getProduct()..." + productName);

              //throw new Exception("error...");  //주석을 출고 실행해 보자.

           }

}

 

[BeforeLoggingAdvice.java]


package onj.hello.aop;

import java.lang.reflect.Method;

import org.springframework.aop.MethodBeforeAdvice;

public class BeforeLoggingAdvice implements MethodBeforeAdvice{

   public void before(Method method, Object[] args, Object target) throws Throwable {

            String findName = (String)args[0];

             System.out.println(method.getName() + "(" + findName + "):: 사전충고");

   }

}

 

/**

사전 충고용 인터페이스

* 이메소드는 대상메소드, 그 메소드에 전달할 인자, 대상객체에 대한 접근점 제공

* 메소드 인자에 접근 가능하므로 런타임중에 파라미터를 사용하여 충고 구현 가능

*/

public interface MethodBeforeAdvice {

   void before(Method method, Object[] args, Object target) throws Throwable ;

}

 

[AfterLoggingAdvice.java]


package onj.hello.aop;

import java.lang.reflect.Method;

import org.springframework.aop.AfterReturningAdvice;

 

public class AfterLoggingAdvice implements AfterReturningAdvice {

           public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {

                      System.out.println("[사후충고]" + method.getName() + "(" + args[0] + ")" );

           }

}

 

/* 사후 충고(AfterReturning Advice)용 인터페이스 */


public interface AfterReturningAdvice {

   void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable;

}

 

[AroundLoggingAdvice.java]


package onj.hello.aop;

import org.aopalliance.intercept.MethodInterceptor;

import org.aopalliance.intercept.MethodInvocation;

public class AroundLoggingAdvice implements MethodInterceptor {

   @Override

   public Object invoke(MethodInvocation invocation) throws Throwable {

      String findName = (String) invocation.getArguments()[0];

      String methodName = (String) invocation.getMethod().getName();

     System.out.println("[주변충고]" + methodName + "(" + findName + ") 메소드 실행전");

     Object obj = invocation.proceed(); // 타켓클래스의 메소드 호출


     System.out.println("[주변충고]" + methodName + "(" + findName + ") 메소드 실행후");

      return obj;

   }

}

 

/* 이전에 사전,사후 충고를 엮었는데 주변충고를 통해 둘 다를 엮을 수 있다.*/


public interface MethodInterceptor {

    Object invoke(MethodInvocation invocation) throws Throwable;

}

 

MethodInterceptor 구현 클래스(주변충고용 클래스)는 대상 메소드의 실제 호출여부를 제어하며 proceed를 통해 호출 타겟 메소드 호출하며, 원래 메소드의 리턴을 대체가능하다.

 

[ThrowsLoggingAdvice.java]


package onj.hello.aop;

 

import org.springframework.aop.ThrowsAdvice;

 

public class ThrowsLoggingAdvice implements ThrowsAdvice {

           public void afterThrowing(Throwable throwable) {

                      System.out.println("[예외충고]에러 발생...");

           }

}

 

/* 예외가 발생했을 때의 행위를 정의, marker interface */


public interface ThrowsAdvice {   }

 

구현대상이 없지만 아래의 메소드중 하나를 포함해야 한다.

void afterThrowing(Throwable throwable);

void afterThrowing(Method method, Object[] args,  Object target, Throwable throwable);

 

[DemoSmallmartApplication.java]


package onj.hello.aop;

import org.springframework.aop.framework.ProxyFactory;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication


public class DemoSmallmartApplication {

   public static void main(String[] args) {

      SpringApplication.run(DemoSmallmartApplication.class, args);  

      SmallMart target = new SmallMartImpl();                

      ProxyFactory pf = new ProxyFactory();

      pf.addAdvice(new BeforeLoggingAdvice());

      pf.addAdvice(new AfterLoggingAdvice());

      pf.addAdvice(new AroundLoggingAdvice());

      pf.addAdvice(new ThrowsLoggingAdvice());

                     

      pf.setTarget(target);           

      try {

          SmallMart proxy = (SmallMart)pf.getProxy();

           proxy.getProducts("생필품");                              

      }

      catch(Exception e) {e.printStackTrace(System.out);  }

   }

}

 

실행결과

 

getProducts(생필품):: 사전충고

[주변충고]getProducts(생필품) 메소드 실행전

[Target Method]getProduct()...생필품

[주변충고]getProducts(생필품) 메소드 실행후

[사후충고]getProducts(생필품)

 

예외를 던지는 부분의 주석을 해제 후

getProducts(생필품):: 사전충고

[주변충고]getProducts(생필품) 메소드 실행전

[Target Method]getProduct()...생필품

에러 발생...

java.lang.Exception: error...

           at onj.hello.aop.SmallMartImpl.getProducts(SmallMartImpl.java:6)

           at onj.hello.aop.SmallMartImpl$$FastClassBySpringCGLIB$$61b83092.invoke(<generated>)

           at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)

           at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:771)

           at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)

           at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)

           at org.springframework.aop.framework.adapter.ThrowsAdviceInterceptor.invoke(ThrowsAdviceInterceptor.java:112)

           at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)

           at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)

           at onj.hello.aop.AroundLoggingAdvice.invoke(AroundLoggingAdvice.java:11)

           at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)

           at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)

           at org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor.invoke(AfterReturningAdviceInterceptor.java:55)

           at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)

           at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)

           at org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor.invoke(MethodBeforeAdviceInterceptor.java:56)

           at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)

           at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)

           at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:691)

           at onj.hello.aop.SmallMartImpl$$EnhancerBySpringCGLIB$$f7f73673.getProducts(<generated>)

           at onj.hello.aop.DemoSmallmartApplication.main(DemoSmallmartApplication.java:23)

 

DemoSmallmartApplication 클래스에서 마우스 우측버튼 -> Run As -> Spring Boot App 또는 Java Application으로 실행 가능


 


 





#스프링충고, #스프링AOP, #스프링advice, #SpringAOP, #스프링DI, #스프링IoC, #SpringDI, #SpringIoC, #자바스프링, #Spring동영상, #Spring강의, #스프링프레임워크, #스프링교육, #스프링학원, #스프링강좌, #스프링강의, #자바학원, #자바, #스프링동영상, #자바동영상, #스프링프레임워크교육, #스프링프레임워크강의, #스프링프레임워크학원   

(C#교육동영상)C# ADO.NET 실습 ODP.NET/ODAC 설치 오라클 함수 호출 실습, C#학원, WPF학원, 닷넷학원, 자바학원

  (C#교육동영상)C# ADO.NET 실습  ODP.NET/ODAC 설치  오라클 함수 호출 실습, C#학원, WPF학원, 닷넷학원, 자바학원 https://www.youtube.com/watch?v=qIPU85yAlzc&list=PLxU-i...