Spring AOP 동적 에이전트 CGLib Aspectj
34302 단어 spring aop
측면 프로 그래 밍 (Aspect) Oriented Programming, 약칭 AOP) 는 일종 의 성명 식 프로 그래 밍 (Declarative Programming)。AOP 의 실현 원 리 는 Proxy / Decorator 디자인 모델 의 일반화 로 볼 수 있 는데 다음 과 같이 Proxy 모델 의 간단 한 예 이다.
Proxy {
innerObject; //
f1() {
//
innerObject.f1(); //
//
}
}
1. 에이 전 트 를 사용 하여 AOP 실현
서비스 클래스 인터페이스 IService. java 설명:
package com.chenzehe.aop;
public interface IService {
int save();
}
구현 클래스:
package com.chenzehe.aop;
public class Service implements IService {
final Logger log = LoggerFactory.getLogger(Service.class);
@Override
public int save() {
log.info("*****save*****");
return 0;
}
}
프 록 시 클래스 ServiceProxy 도 IService 인 터 페 이 스 를 실현 하고 내부 호출 Service 의 실현 방법 을 실현 하 며 앞 과 배경 에 자신의 절단면 방법 을 추가 합 니 다.
package com.chenzehe.aop;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ServiceProxy implements IService {
final Logger log = LoggerFactory.getLogger(ServiceProxy.class);
private IService service;
public ServiceProxy(IService service) {
this.service = service;
}
@Override
public int save() {
int result;
log.debug("*****Before*****");
result = service.save();
log.debug("*****After*****");
return result;
}
}
유닛 테스트 클래스 프 록 시 테스트 사용 ServiceProxy 추가:
import org.junit.Test;
public class ProxyTest {
@Test
public void testSave() {
IService service = new ServiceProxy(new Service());
service.save();
}
}
:
ServiceProxy - *****Before*****
*****save*****
ServiceProxy - *****After*****
2. 동적 에이전트 로 AOP 구현
위의 코드 는 가장 간단 한 AOP 기능 을 실현 했다. 그러나 프로젝트 에 Service 와 같은 종류 가 많다 면 ServiceProxy 와 같은 프 록 시 류 를 많이 써 서 실현 해 야 하기 때문에 동적 코드 방법 으로 실현 해 야 한다. 즉, Invocation Handler 의 인 터 페 이 스 를 실현 하 는 것 이다. 이런 종 류 는 JVM 에서 특정한 방법 을 호출 할 때 동태 적 으로 어떤 방법 을 위해 무엇 을 할 수 있 는 지,다음 코드, IService 인터페이스 와 구현 클래스 Service 가 변 하지 않 습 니 다. 동적 프 록 시 구현 클래스 DynamicProxy 를 추가 합 니 다.
/**
* Huisou.com Inc.
* Copyright (c) 2011-2012 All Rights Reserved.
*/
package com.chenzehe.aop;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class DynamicProxy implements InvocationHandler {
final Logger log = LoggerFactory.getLogger(ServiceProxy.class);
/**
* ( )
*/
private Object delegate;
/**
* ( )
*/
public Object bind(Object delegate) {
this.delegate = delegate;
return Proxy.newProxyInstance(this.delegate.getClass().getClassLoader(), this.delegate.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result;
log.debug("*****Before*****");
result = method.invoke(this.delegate, args);
log.debug("*****After*****");
return result;
}
}
유닛 테스트 코드 는 다음 과 같 습 니 다.
package com.chenzehe.aop;
import org.junit.Test;
public class DynamicProxyTest {
@Test
public void testSave() {
IService service = (IService) new DynamicProxy().bind(new Service());
service.save();
}
}
:
ServiceProxy - *****Before*****
*****save*****
ServiceProxy - *****After*****
3. 알림 디 결합
위의 코드 는 절단면 통 지 를 실 현 했 지만 알림 방법 은 모두 대리 방법 에서 이 루어 졌 습 니 다. 이렇게 결합 도가 너무 높 아서 우 리 는 하나의 인 터 페 이 스 를 추상 화 할 수 있 습 니 다. 이 인터페이스 에는 두 가지 방법 만 있 습 니 다. 하 나 는 대리 대상 이 방법 을 실행 하기 전에 실행 하 는 방법 입 니 다. 우 리 는 before 라 고 이름 을 지 었 습 니 다.두 번 째 방법 은 대리 대상 이 방법 을 실행 한 후에 실행 하 는 방법 입 니 다. 우 리 는 after 라 고 이름 을 지 었 습 니 다. 인 터 페 이 스 는 다음 과 같이 정의 합 니 다.
package com.chenzehe.aop;
import java.lang.reflect.Method;
public interface IOperation {
/**
*
*
* @param method
*/
void before(Method method);
/**
*
*
* @param method
*/
void after(Method method);
}
우 리 는 위의 인 터 페 이 스 를 실현 하 는 종 류 를 쓰 러 간다. 우 리 는 그의 진정한 조작 자가 될 것 이다. 예 를 들 어 다음은 로그 조작 자의 종류 이다.
/**
* Huisou.com Inc.
* Copyright (c) 2011-2012 All Rights Reserved.
*/
package com.chenzehe.aop;
import java.lang.reflect.Method;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class LoggerOperation implements IOperation {
final Logger log = LoggerFactory.getLogger(LoggerOperation.class);
@Override
public void before(Method method) {
log.info("Before:" + method.getName());
}
@Override
public void after(Method method) {
log.info("After:" + method.getName());
}
}
동적 에이전트 구현 클래스:
/**
* Huisou.com Inc.
* Copyright (c) 2011-2012 All Rights Reserved.
*/
package com.chenzehe.aop;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class OperationDynamicProxy implements InvocationHandler {
/**
* ( )
*/
private Object delegate;
/**
*
*/
private Object operation;
public OperationDynamicProxy() {
}
/**
* ( )
*/
public Object bind(Object delegate, Object operation) {
this.delegate = delegate;
this.operation = operation;
return Proxy.newProxyInstance(this.delegate.getClass().getClassLoader(), this.delegate.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result;
//
Class clazz = this.operation.getClass();
// before
Method start = clazz.getDeclaredMethod("before", new Class[] { Method.class });
// before
start.invoke(this.operation, new Object[] { method });
//
result = method.invoke(this.delegate, args);
// end
Method end = clazz.getDeclaredMethod("after", new Class[] { Method.class });
// end
end.invoke(this.operation, new Object[] { method });
return result;
}
}
테스트 클래스:
/**
* Huisou.com Inc.
* Copyright (c) 2011-2012 All Rights Reserved.
*/
package com.chenzehe.aop;
import org.junit.Test;
public class OperationDynamicProxyTest {
@Test
public void testSave() {
IService service = (IService) new OperationDynamicProxy().bind(new Service(), new LoggerOperation());
service.save();
}
}
:
LoggerOperation - Before:save
*****save*****
LoggerOperation - After:save
4 、 CGLib 로 구현
위 에서 AOP 에서 피 에이전트 대상 은 모두 인 터 페 이 스 를 제공 합 니 다. 가끔 은 우리 의 수요 에서 피 에이전트 클래스 가 인 터 페 이 스 를 제공 하지 않 을 때 CGLib 를 사용 하여 이 루어 집 니 다. CGLib 실현 원 리 는 피 에이전트 클래스 를 계승 하고 피 에이전트 클래스 를 다시 쓰 는 방법 입 니 다. 그리고 재 작성 방법 에 자신의 절단면 방법 을 추가 하 는 것 입 니 다.
제공 되 지 않 은 클래스:
/**
* Huisou.com Inc.
* Copyright (c) 2011-2012 All Rights Reserved.
*/
package com.chenzehe.aop;
public class ServiceNotInterface {
final Logger log = LoggerFactory.getLogger(ServiceNotInterface.class);
public int save() {
log.info("*****save*****");
return 0;
}
}
CGLib 구현 클래스:
/**
* Huisou.com Inc.
* Copyright (c) 2011-2012 All Rights Reserved.
*/
package com.chenzehe.aop;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class CGLibProxy implements MethodInterceptor {
/**
*
*/
private Object delegate;
/**
*
*/
private Object operation;
/**
*
*/
public Object bind(Object delegate, Object operation) {
this.delegate = delegate;
this.operation = operation;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.delegate.getClass());
//
enhancer.setCallback(this);
//
return enhancer.create();
}
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object result;
//
Class clazz = this.operation.getClass();
// before
Method start = clazz.getDeclaredMethod("before", new Class[] { Method.class });
// before
start.invoke(this.operation, new Object[] { method });
//
result = methodProxy.invokeSuper(proxy, args);
// end
Method end = clazz.getDeclaredMethod("after", new Class[] { Method.class });
// end
end.invoke(this.operation, new Object[] { method });
return result;
}
}
테스트 클래스:
/**
* Huisou.com Inc.
* Copyright (c) 2011-2012 All Rights Reserved.
*/
package com.chenzehe.aop;
import java.lang.reflect.Method;
import org.junit.Test;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class CGLibProxyTest {
@Test
public void testSave() {
ServiceNotInterface service = (ServiceNotInterface) new CGLibProxy().bind(new ServiceNotInterface(), new LoggerOperation());
service.save();
}
}
:
LoggerOperation - Before:save
*****save*****
LoggerOperation - After:save
5. Spring AOP 개념
절단면 (aspect): 업무 방법 을 삽입 하 는 클래스 입 니 다.연결 점 (joinpoint): 절단면 류 와 업무 류 의 연결 점 입 니 다. 사실은 업무 방법의 기본 속성 을 밀봉 하여 알림 의 매개 변수 로 분석 합 니 다.알림 (advice): 절단면 류 에서 업무 방법 에 대해 추가 로 처리 하 는 방법 을 설명 합 니 다.접점 (pointcut): 업무 클래스 에서 지정 한 방법 으로 절단면 으로 들 어 가 는 점 입 니 다.사실은 어떤 방법 을 절단면 으로 자 르 는 곳 으로 지정 하 는 것 이다.대상 (target object): 대리 대상.AOP 에이전트 (aop proxy): 에이전트 대상.사전 알림 (before advice): 접점 에 들 어가 기 전에 실행 합 니 다.후방 알림 (after returning advice): 삽입점 에서 실행 이 끝 난 후 알림 을 실행 합 니 다.서 라운드 알림 (around advice): 접근 점 을 포위 하고 호출 방법 전후 로 사용자 정의 행 위 를 완성 합 니 다.이상 알림 (after throwing advice): 접점 에서 이상 을 던 진 후 알림 을 실행 합 니 다.
Spring 은 AOP 를 실현 하 는 세 가지 방식, Spring 인터페이스 방식, schema 설정 방식 과 주해 방식 의 세 가지 실현 방식 을 제공 했다.
6. 인터페이스 방식
Spring AOP 인 터 페 이 스 를 이용 하여 AOP 를 실현 하 는 것 은 주로 사용자 정의 알림 을 지정 하여 spring AOP 메커니즘 을 식별 할 수 있 도록 하기 위 한 것 이다.주요 인터페이스: 사전 알림 MethodBeforeAdvice, 사후 알림: AfterReturning Advice, 서 라운드 알림: MethodInterceptor, 이상 알림: ThrowsAdvice.다음 코드:
위의 인터페이스 IService 와 구현 클래스 Service 를 사용 합 니 다.
사전 알림:
/**
* Huisou.com Inc.
* Copyright (c) 2011-2012 All Rights Reserved.
*/
package com.chenzehe.aop;
import java.lang.reflect.Method;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.MethodBeforeAdvice;
/**
*
*/
public class BaseBeforeAdvice implements MethodBeforeAdvice {
final Logger log = LoggerFactory.getLogger(BaseBeforeAdvice.class);
/**
* method : <br>
* args : <br>
* target :
*/
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
log.info("=========== beforeAdvice()============
");
log.info(" " + target + " ");
log.info(method + " ");
log.info("
");
}
}
나중에 알림:
/**
* Huisou.com Inc.
* Copyright (c) 2011-2012 All Rights Reserved.
*/
package com.chenzehe.aop;
import java.lang.reflect.Method;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.AfterReturningAdvice;
/**
*
*/
public class BaseAfterReturnAdvice implements AfterReturningAdvice {
final Logger log = LoggerFactory.getLogger(BaseAfterReturnAdvice.class);
/**
* returnValue : , <br>
* method : <br>
* args : <br>
* target :
*/
@Override
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
log.info("========== afterReturning()===========
");
}
}
서 라운드 알림:
/**
* Huisou.com Inc.
* Copyright (c) 2011-2012 All Rights Reserved.
*/
package com.chenzehe.aop;
import java.lang.reflect.Method;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
*/
public class BaseAroundAdvice implements MethodInterceptor {
final Logger log = LoggerFactory.getLogger(BaseAroundAdvice.class);
/**
* invocation :
*/
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
log.info("=========== around !===========
");
//
log.info(" : !
");
//
Object[] args = invocation.getArguments();
//
Method method = invocation.getMethod();
//
Object target = invocation.getThis();
// : proceed() ,
Object returnValue = invocation.proceed();
log.info("=========== around !===========
");
log.info(" :" + args + ";" + method + ";" + target + ";" + returnValue + "
");
log.info(" : !
");
return returnValue;
}
}
이상 알림:
/**
* Huisou.com Inc.
* Copyright (c) 2011-2012 All Rights Reserved.
*/
package com.chenzehe.aop;
import java.lang.reflect.Method;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.ThrowsAdvice;
/**
* , 。
*/
public class BaseAfterThrowsAdvice implements ThrowsAdvice {
final Logger log = LoggerFactory.getLogger(BaseAfterThrowsAdvice.class);
/**
* ,
*
* @param method
* :
* @param args
* :
* @param target
* :
* @param throwable
* : , , 。
*/
public void afterThrowing(Method method, Object[] args, Object target, Throwable throwable) {
log.info(" ");
}
}
지정 한 접점 정의:
/**
* Huisou.com Inc.
* Copyright (c) 2011-2012 All Rights Reserved.
*/
package com.chenzehe.aop;
import java.lang.reflect.Method;
import org.springframework.aop.support.NameMatchMethodPointcut;
/**
* , 。 <br>
* NameMatchMethodPointcut ,
*/
public class Pointcut extends NameMatchMethodPointcut {
private static final long serialVersionUID = 5891054717975242200L;
@SuppressWarnings("rawtypes")
@Override
public boolean matches(Method method, Class targetClass) {
//
this.setMappedName("delete");
//
String[] methods = { "delete", "save" };
// “ * ”
// this.setMappedName("get*");
this.setMappedNames(methods);
return super.matches(method, targetClass);
}
}
설정:
<?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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
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.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"
default-autowire="byName">
<!-- ============================== spring aop ================================ -->
<!-- -->
<bean id="service" class="com.chenzehe.aop.Service" />
<!-- -->
<bean id="baseBefore" class="com.chenzehe.aop.BaseBeforeAdvice" />
<bean id="baseAfterReturn" class="com.chenzehe.aop.BaseAfterReturnAdvice" />
<bean id="baseAfterThrows" class="com.chenzehe.aop.BaseAfterThrowsAdvice" />
<bean id="baseAround" class="com.chenzehe.aop.BaseAroundAdvice" />
<!-- -->
<bean id="pointcut" class="com.chenzehe.aop.Pointcut" />
<!-- , -->
<bean id="matchBeforeAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
<property name="pointcut">
<ref bean="pointcut" />
</property>
<property name="advice">
<ref bean="baseBefore" />
</property>
</bean>
<!-- ProxyFactoryBean -->
<bean id="businessProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<!-- , -->
<property name="proxyInterfaces">
<value>com.chenzehe.aop.IService</value>
</property>
<!-- -->
<property name="target">
<ref local="service" />
</property>
<!-- -->
<property name="interceptorNames">
<list>
<value>matchBeforeAdvisor</value>
<value>baseAfterReturn</value>
<value>baseAround</value>
</list>
</property>
</bean>
</beans>
테스트 클래스:
/**
* Huisou.com Inc.
* Copyright (c) 2011-2012 All Rights Reserved.
*/
package com.chenzehe.aop;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringAopInterfaceTest {
@Test
public void testSpringAopInterface() {
ApplicationContext context = new ClassPathXmlApplicationContext("spring-aop.xml");
IService service = (IService) context.getBean("businessProxy");
service.save();
}
}
출력:
BaseBeforeAdvice - =========== beforeAdvice()============
BaseBeforeAdvice - com.chenzehe.aop.Service@1e136a8
BaseBeforeAdvice - public abstract int com.chenzehe.aop.IService.save()
BaseBeforeAdvice -
BaseAroundAdvice - =========== around !===========
BaseAroundAdvice - : !
Service - *****save*****
BaseAroundAdvice - =========== around !===========
BaseAroundAdvice - :[Ljava.lang.Object;@ee558f;public abstract int com.chenzehe.aop.IService.save();com.chenzehe.aop.Service@1e136a8;0
BaseAroundAdvice - : !
BaseAfterReturnAdvice - ========== afterReturning()===========
선행 방법 은 삽입점 방법 전에 실행 되 고, 선행 방법 은 삽입점 방법 이 실 행 된 후에 실행 되 며, 서 라운드 방법 은 삽입점 방법 이 실 행 될 때 까지 동료의 방법 이 끝나 도 대응 하 는 부분 을 실행한다.주로 proceed () 방법 을 호출 하여 접점 방법 을 실행 합 니 다.businessProxy 라 는 bean 을 설정 할 때 Proxy Factory Bean 클래스 에서 'proxy Interfaces 인자' 를 지정 합 니 다.여기 서 그 를 IService 인터페이스 로 설정 했다.프로젝트 개발 과정 에서 업무 류 에 대응 하 는 인터페이스 가 있어 IOC 디 결합 을 편리 하 게 이용 하기 때문이다.그러나 스프링 AOP 는 인터페이스 가 없 는 에이 전 트 를 지원 할 수 있다.이것 이 바로 cglib. jar 의 가방 을 가 져 와 야 하 는 이유 입 니 다.목표 접근 대상 에 실현 인터페이스 가 있 으 면 spring 은 기본적으로 jdk 동적 대 리 를 통 해 대리 류 를 실현 합 니 다.인터페이스 가 없 으 면 cglib 를 통 해 프 록 시 클래스 를 구현 합 니 다.
7 、 AOP 설정 을 위해 aspectj 사용
위 에 인터페이스 가 구현 되 지 않 은 비 즈 니스 클래스 ServiceNotInterface 를 사용 합 니 다.
절단면 클래스 AspectAdvice 를 정의 합 니 다. 모든 알림 이 포함 되 어 있 습 니 다.
package com.chenzehe.aop;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
*
*/
public class AspectAdvice {
final Logger log = LoggerFactory.getLogger(AspectAdvice.class);
/**
*
*
* @param jp
*
*/
public void doBefore(JoinPoint jp) {
log.info("=========== before advice============
");
log.info("
");
}
/**
*
*
* @param jp
*
* @param result
*
*/
public void doAfter(JoinPoint jp, String result) {
log.info("========== after advice===========
");
}
/**
*
*
* @param pjp
*
*/
public void doAround(ProceedingJoinPoint pjp) throws Throwable {
log.info("=========== around !===========
");
//
log.info(" : !
");
//
Object[] args = pjp.getArgs();
//
String method = pjp.getSignature().getName();
//
Object target = pjp.getTarget();
// : proceed() ,
Object result = pjp.proceed();
log.info(" :" + args + ";" + method + ";" + target + ";" + result + "
");
log.info(" : !
");
}
/**
*
*
* @param jp
* @param e
*/
public void doThrow(JoinPoint jp, Throwable e) {
log.info(" ");
}
}
프로필:
<?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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
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.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"
default-autowire="byName">
<!-- ============================== spring aspectj AOP================================ -->
<!-- -->
<bean id="aspectBusiness" class="com.chenzehe.aop.ServiceNotInterface" />
<!-- -->
<bean id="aspectAdvice" class="com.chenzehe.aop.AspectAdvice" />
<aop:config>
<aop:aspect id="businessAspect" ref="aspectAdvice">
<!-- -->
<aop:pointcut id="point_cut" expression="execution(* com.chenzehe.aop.ServiceNotInterface.*(..))" />
<!-- -->
<aop:before method="doBefore" pointcut-ref="point_cut" />
<!-- returning -->
<aop:after-returning method="doAfter"
pointcut-ref="point_cut" returning="result" />
<aop:around method="doAround" pointcut-ref="point_cut" />
<aop:after-throwing method="doThrow" pointcut-ref="point_cut"
throwing="e" />
</aop:aspect>
</aop:config>
</beans>
테스트 클래스:
/**
* Huisou.com Inc.
* Copyright (c) 2011-2012 All Rights Reserved.
*/
package com.chenzehe.aop;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringAopAspectjTest {
@Test
public void testSpringAopAspectj() {
ApplicationContext context = new ClassPathXmlApplicationContext("spring-aspectj-aop.xml");
ServiceNotInterface service = (ServiceNotInterface) context.getBean("aspectBusiness");
service.save();
}
}
출력:
AspectAdvice - =========== before advice============
AspectAdvice -
DefaultListableBeanFactory - Returning cached instance of singleton bean 'aspectAdvice'
AspectAdvice - =========== around !===========
AspectAdvice - : !
ServiceNotInterface - *****save*****
AspectAdvice - :[Ljava.lang.Object;@edf389;save;com.chenzehe.aop.ServiceNotInterface@59fb21;0
AspectAdvice - : !
8. aspectj 주 해 를 사용 하여 AOP 를 설정 합 니 다.
주석 기반 service 클래스:
/**
* Huisou.com Inc.
* Copyright (c) 2011-2012 All Rights Reserved.
*/
package com.chenzehe.aop;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
/**
* @description
*
* @author chenzehe
* @email [email protected]
*/
@Component
public class ServiceAnonotation {
final Logger log = LoggerFactory.getLogger(ServiceAnonotation.class);
public int save() {
log.info("*****save*****");
return 0;
}
}
주석 기반 절단면:
package com.chenzehe.aop;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
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;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
/**
*
*
*/
@Component
@Aspect
public class AspectAdviceAnonotation {
final Logger log = LoggerFactory.getLogger(AspectAdviceAnonotation.class);
/**
* , 。
*/
@Pointcut("execution(* com.chenzehe.aop.*.*(..))")
public void anyMethod() {
}
/**
*
*
* @param jp
*/
@Before(value = "execution(* com.chenzehe.aop.*.*(..))")
public void doBefore(JoinPoint jp) {
log.info("=========== before advice============
");
log.info("
");
}
/**
*
*
* @param jp
*
* @param result
*
*/
@AfterReturning(value = "anyMethod()", returning = "result")
public void doAfter(JoinPoint jp, String result) {
log.info("========== after advice===========
");
}
/**
*
*
* @param pjp
*
*/
@Around(value = "execution(* com.chenzehe.aop.*.*(..))")
public void doAround(ProceedingJoinPoint pjp) throws Throwable {
log.info("=========== around !===========
");
//
log.info(" : !
");
//
Object[] args = pjp.getArgs();
//
String method = pjp.getSignature().getName();
//
Object target = pjp.getTarget();
// : proceed() ,
Object result = pjp.proceed();
log.info(" :" + args + ";" + method + ";" + target + ";" + result + "
");
log.info(" : !
");
}
/**
*
*
* @param jp
* @param e
*/
@AfterThrowing(value = "execution(* com.chenzehe.aop.*.*(..))", throwing = "e")
public void doThrow(JoinPoint jp, Throwable e) {
log.info(" ");
}
}
프로필:
<?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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
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.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"
default-autowire="byName">
<context:component-scan base-package="com.chenzehe.aop" />
<!-- aop -->
<aop:aspectj-autoproxy />
</beans>
테스트 클래스:
/**
* Huisou.com Inc.
* Copyright (c) 2011-2012 All Rights Reserved.
*/
package com.chenzehe.aop;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @description
*
* @author chenzehe
* @email [email protected]
*/
public class SpringAopAspectjAnonotationTest {
@Test
public void testSpringAopAspectjAnonotation() {
ApplicationContext context = new ClassPathXmlApplicationContext("spring-aspectj-anonotation-aop.xml");
ServiceAnonotation service = (ServiceAnonotation) context.getBean("serviceAnonotation");
service.save();
}
}
출력:
AspectAdviceAnonotation - =========== before advice============
AspectAdviceAnonotation -
AspectAdviceAnonotation - =========== around !===========
AspectAdviceAnonotation - : !
ServiceAnonotation - *****save*****
AspectAdviceAnonotation - :[Ljava.lang.Object;@7ecd78;save;com.chenzehe.aop.ServiceAnonotation@16be68f;0
AspectAdviceAnonotation - : !