基於代理的spring aop中多種通知實現
阿新 • • 發佈:2018-12-12
不需要引入額外的jar包,只需引入需要模組的spring內部jar包即可.
介面結構
標註的都是標記介面,其中大多數有明確約定的介面實現,只有異常通知介面沒有,但有其預設約定.
Advice | spring aop通知的頂層標記介面 |
MethodBeforeAdvice | 約定前置通知的介面 |
AfterReturningAdvice | 約定返回通知的介面 因後置通知無約定介面,可使用其進行後置通知. |
ThrowsAdvice | 約定異常通知的介面 無具體約定,但有預設的實現規範. |
MethodInterceptor | 約定環繞通知的介面 |
ProxyFactory | spring內建的建立代理的工具類 |
目標物件類
package siye; public class TargetObj { public void work() { System.out.println("work......"); } public void throwOwn() { throw new RuntimeException(); } }
測試前置通知的實現
package siye; import java.lang.reflect.Method; import org.aopalliance.aop.Advice; import org.springframework.aop.MethodBeforeAdvice; import org.springframework.aop.framework.ProxyFactory; public class UnitTestMethodBeforeAdviceImpl { public static void main(String[] args) { TargetObj targetObj = new TargetObj(); Advice adviceImpl = new MethodBeforeAdviceImpl(); ProxyFactory proxyFactory = new ProxyFactory(); proxyFactory.setTarget(targetObj); proxyFactory.addAdvice(adviceImpl); TargetObj obj = (TargetObj) proxyFactory.getProxy(); obj.work(); } } class MethodBeforeAdviceImpl implements MethodBeforeAdvice { @Override public void before(Method method, Object[] args, Object target) throws Throwable { System.out.println("方法即將被呼叫"); } }
測試返回通知(後置通知)的實現
package siye;
import java.lang.reflect.Method;
import org.aopalliance.aop.Advice;
import org.springframework.aop.AfterReturningAdvice;
import org.springframework.aop.framework.ProxyFactory;
public class UnitTestAfterReturningAdviceImpl
{
public static void main(String[] args)
{
TargetObj targetObj = new TargetObj();
Advice adviceImpl = new AfterReturningAdviceImpl();
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setTarget(targetObj);
proxyFactory.addAdvice(adviceImpl);
TargetObj obj = (TargetObj) proxyFactory.getProxy();
obj.work();
}
}
class AfterReturningAdviceImpl implements AfterReturningAdvice
{// 後置通知暫未找到藉口,可用此介面替代.
@Override
public void afterReturning(Object returnValue, Method method,
Object[] args, Object target) throws Throwable
{
System.out.println("方法已返回值,是" + returnValue);
}
}
測試異常通知的實現
package siye;
import org.aopalliance.aop.Advice;
import org.junit.Test;
import org.springframework.aop.ThrowsAdvice;
import org.springframework.aop.framework.ProxyFactory;
class UnitTest
{
}
/*
* ThrowsAdvice是標記介面
* 在aop包中,不同其他通知介面,沒有約定的方法.
* 原始碼文件中有預設約定.
*
* 規定的格式
* void afterThrowing([Method, args, target], ThrowableSubclass);
* 前三個引數是可選的,但必須一同出現,第四個引數是必選的.
* e.g.
* public void afterThrowing(Exception ex)
* public void afterThrowing(RemoteException)
* public void afterThrowing(Method method, Object[] args, Object target,
* Exception ex)
* public void afterThrowing(Method method, Object[] args, Object target,
* ServletException ex)
*
* The first three arguments are optional, and only useful if we want further
* information about the joinpoint, as in AspectJ after-throwing advice.
*/
public class UnitTestThrowsAdviceImpl implements ThrowsAdvice
{// 此類必須標記為public
// IllegalAccessException: Class
// org.springframework.aop.framework.adapter.ThrowsAdviceInterceptor can not
// access a member of class
public void afterThrowing(Exception e)
{
System.out.println("方法丟擲異常,型別是" + e.toString());
}
// 單元測試
@Test
public void test()
{
TargetObj targetObj = new TargetObj();
Advice adviceImpl = new UnitTestThrowsAdviceImpl();
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setTarget(targetObj);
proxyFactory.addAdvice(adviceImpl);
TargetObj obj = (TargetObj) proxyFactory.getProxy();
try
{
obj.throwOwn();
} catch (Exception e)
{
}
}
}
測試環繞通知的實現
package siye;
import org.aopalliance.aop.Advice;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.framework.ProxyFactory;
public class UnitTestMethodInterceptorImpl
{
public static void main(String[] args)
{
TargetObj targetObj = new TargetObj();
Advice interceptorImpl = new MethodInterceptorImpl();
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setTarget(targetObj);
proxyFactory.addAdvice(interceptorImpl);
TargetObj obj = (TargetObj) proxyFactory.getProxy();
obj.work();
}
}
class MethodInterceptorImpl implements MethodInterceptor
{
@Override
public Object invoke(MethodInvocation invocation) throws Throwable
{
System.out.println("方法即將開始");
// 通過反射機制呼叫目標的方法
Object object = invocation.proceed();
System.out.println("方法執行結束");
return object;
}
}