2014년 2월 3일 월요일

@AspectJ 어노테이션을 이용한 AOP구현예제(Spring Framework3.X AOP구현하기,Advice, Pointcut, Aspect), 스프링AOP 강좌교육,오라클자바커뮤니티,오엔제이프로그래밍실무교육센터

@AspectJ 어노테이션을 이용한 AOP구현예제(Spring Framework3.X AOP구현하기,Advice, Pointcut, Aspect), 스프링AOP 강좌교육,오라클자바커뮤니티,오엔제이프로그래밍실무교육센터
- 다음과 같은 인터페이스와 타겟 클레스가 있다. 


package onj.aop.aspectjannotation;

interface OnjWorld {
public void onjHello();
public void onjHello2() throws Exception;
}


package onj.aop.aspectjannotation;
//Target Class
public class OnjWorldImpl implements OnjWorld {
public void onjHello() {
System.out.println("OnJ에오신것을 환영합니다.");
}

public void onjHello2() throws Exception {
System.out.println("OnJ2에오신것을 환영합니다.");
throw new Exception("OnJ Exception...");
}
}

위 OnjWorldImpl이 타겟 클래스이다. onjHello2 로 시작하는 메소드에 스프링 충고를 내릴려고 한다. 
충고(Advice)는 적당히 콘솔화면에 출력하는 정도로 만들고... 
before advice, around advice, throws advice, after,after returning advice를 구현하시오. 

- @AspectJ Annotation을 이용하여 구현해 보았다.

가장 핵심이 되는 클래스는 Aspect인 AonjLoggingAspect이다. 그안에 충고, 포인트컷에 대한 AspectJ 표현식등이 기술되어 Aspect(Advice + PointCut)를   만든다.

1. OnjWorld.java

package onj.aop.aspectjannotation;

interface OnjWorld {
public void onjHello();
public void onjHello2() throws Exception;
}

2. OnjWorldImpl.java

package onj.aop.aspectjannotation;

public class OnjWorldImpl implements OnjWorld {
public void onjHello() {
System.out.println("OnJ에오신것을 환영합니다.");
}

public void onjHello2() throws Exception {
System.out.println("OnJ2에오신것을 환영합니다.");
throw new Exception("OnJ Exception...");
}
}


3.  OnjLoggingAspect.java


package onj.aop.aspectjannotation;

import java.util.Arrays;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect
public class OnjLoggingAspect {
 //사전충고(Before Advice)
 @Before("execution (* onj.aop.aspectjannotation.OnjWorld.onjHello(..))")
 public void logBefore(JoinPoint joinPoint){
  System.out.println("<<<<< Advice-->logBefore()...");
  joinPoint.getSignature().getName();
 }
 
 //사후중고(After Advice), 타겟메소드 실행 후 즉시 실행
 @After("execution (* onj.aop.aspectjannotation.OnjWorld.onjHello(..))")
 public void logAfter(JoinPoint joinPoint){
  System.out.println("<<<<< Advice --> logAfter()...");
  joinPoint.getSignature().getName();
 }
 
 //사후중고(After Returnning Advice), 타겟메소드 리턴 후 실행
 @AfterReturning(pointcut = "execution (* onj.aop.aspectjannotation.OnjWorld.onjHello(..))", returning="result")
 public void logAfterReturning(JoinPoint joinPoint, Object result){
  System.out.println("<<<<< Advice --> logAfterReturning()...");
  joinPoint.getSignature().getName();
  System.out.println("<<<<< return value is " + result);
 }
 
 //주변충고(Around Advice), 타겟메소드 실행전, 리턴 후 두번 충고 실행 
 @Around("execution (* onj.aop.aspectjannotation.OnjWorld.onjHello(..))")
 public String logAround(ProceedingJoinPoint joinPoint) throws Throwable{
  System.out.println("<<<<< Advice --> logAournd()...");
  joinPoint.getSignature().getName();
  Arrays.toString(joinPoint.getArgs());
  System.out.println("<<<<< Around before is renning!");
  joinPoint.proceed();
  System.out.println("<<<<< Around after is renning!)");
  return "이 문장으로 원래 타겟메소드 리턴이 대체됨!";
 }
 
 //예외충고(Throws Advice), 예외가 발생했을 때 예외전에 충고실행
 @AfterThrowing(pointcut = "execution (* onj.aop.aspectjannotation.OnjWorld.onjHello2(..))", throwing = "error")
 public void logAfterThrowing(JoinPoint joinPoint, Throwable error){
  System.out.println("<<<<< Advice --> logAfterThrowing()...");
  joinPoint.getSignature().getName();
  System.out.println("<<<<< Exception " +error);
 }
}


4. OnjClient.java

package onj.aop.aspectjannotation;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class OnjClient {
 public static void main(String[] args) throws Exception{
  ApplicationContext ctx =new ClassPathXmlApplicationContext("aspectjannotation.xml"); 
  
  OnjWorld o = (OnjWorld)ctx.getBean("onjWorld");
  
  o.onjHello();
  o.onjHello2();
 }
}



5. src/main/resource/aspectjannotation.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"
 xmlns:aop="http://www.springframework.org/schema/aop"
 xsi:schemaLocation="http://www.springframework.org/schema/beans 
 http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
 http://www.springframework.org/schema/aop 
 http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">
 
 <aop:aspectj-autoproxy />
 
 <bean id="onjWorld" class="onj.aop.aspectjannotation.OnjWorldImpl" />
 <bean id="onjLogger" class="onj.aop.aspectjannotation.OnjLoggingAspect" />
 
</beans>


6.[결과]

SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/C:/java/lib/slf4j-log4j12-1.7.5.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/C:/Documents%20and%20Settings/Administrator/.m2/repository/org/slf4j/slf4j-log4j12/1.6.6/slf4j-log4j12-1.6.6.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [org.slf4j.impl.Log4jLoggerFactory]
INFO : org.springframework.context.support.ClassPathXmlApplicationContext - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@6250d2: startup date [Tue Feb 04 07:20:40 KST 2014]; root of context hierarchy
INFO : org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loading XML bean definitions from class path resource [aspectjannotation.xml]
INFO : org.springframework.beans.factory.support.DefaultListableBeanFactory - Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@1518883: defining beans [org.springframework.aop.config.internalAutoProxyCreator,onjWorld,onjLogger]; root of factory hierarchy
<<<<< Advice --> logAournd()...
<<<<< Around before is renning!
<<<<< Advice-->logBefore()...
OnJ에오신것을 환영합니다.
<<<<< Around after is renning!)
<<<<< Advice --> logAfter()...
<<<<< Advice --> logAfterReturning()...
<<<<< return value is 이 문장으로 원래 타겟메소드 리턴이 대체됨!
OnJ2에오신것을 환영합니다.
<<<<< Advice --> logAfterThrowing()...
<<<<< Exception java.lang.Exception: OnJ Exception...
Exception in thread "main" java.lang.Exception: OnJ Exception...
at onj.aop.aspectjannotation.OnjWorldImpl.onjHello2(OnjWorldImpl.java:10)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:55)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:91)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
at onj.aop.aspectjannotation.$Proxy9.onjHello2(Unknown Source)
at onj.aop.aspectjannotation.OnjClient.main(OnjClient.java:12)



댓글 없음:

댓글 쓰기