spring aop之鏈?zhǔn)秸{(diào)用的實(shí)現(xiàn)
概述
AOP(Aspect Orient Programming),我們一般稱為面向方面(切面)編程,作為面向?qū)ο蟮囊环N補(bǔ)充,用于處理系統(tǒng)中分布于各個(gè)模塊的橫切關(guān)注點(diǎn),比如事務(wù)管理、日志、緩存等等。 Spring AOP采用的是動態(tài)代理,在運(yùn)行期間對業(yè)務(wù)方法進(jìn)行增強(qiáng),所以不會生成新類,Spring AOP提供了對JDK動態(tài)代理的支持以及CGLib的支持。本章我們不關(guān)注aop代理類的實(shí)現(xiàn),我簡單實(shí)現(xiàn)一個(gè)指定次序的鏈?zhǔn)秸{(diào)用。
實(shí)現(xiàn)鏈?zhǔn)秸{(diào)用的
MethodInterceptor定義攔截器鏈,MethodInvocation 遞歸進(jìn)入下一個(gè)攔截器鏈中。類圖如下:

MethodInterceptor
public interface MethodInterceptor {
Object invoke(MethodInvocation invocation) throws Throwable;
}
MethodInvocation
public interface MethodInvocation {
Object proceed() throws Throwable;
}
AbstractAspectJAdvice
抽象類,實(shí)現(xiàn)MethodInterceptor
public abstract class AbstractAspectJAdvice implements MethodInterceptor{
private Method adviceMethod;
private Object adviceObject;
public AbstractAspectJAdvice(Method adviceMethod, Object adviceObject) {
this.adviceMethod = adviceMethod;
this.adviceObject = adviceObject;
}
public Method getAdviceMethod() {
return this.adviceMethod;
}
public void invokeAdviceMethod() throws Throwable {
adviceMethod.invoke(adviceObject);
}
}
AspectJBeforeAdvice
前置通知
public class AspectJBeforeAdvice extends AbstractAspectJAdvice {
public AspectJBeforeAdvice(Method method, Object adviceObject) {
super(method, adviceObject);
}
@Override
public Object invoke(MethodInvocation invocation) throws Throwable{
this.invokeAdviceMethod();
Object o = invocation.proceed();
return o;
}
}
AspectJAfterReturningAdvice
后置通知
public class AspectJAfterReturningAdvice extends AbstractAspectJAdvice {
public AspectJAfterReturningAdvice(Method method, Object adviceObject) {
super(method, adviceObject);
}
@Override
public Object invoke(MethodInvocation invocation) throws Throwable{
Object o = invocation.proceed();
this.invokeAdviceMethod();
return o;
}
}
ReflectiveMethodInvocation
實(shí)現(xiàn)MethodInvocation,proceed()方法遞歸實(shí)現(xiàn)鏈?zhǔn)秸{(diào)用。
public class ReflectiveMethodInvocation implements MethodInvocation {
private final Object targetObject;
private final Method targetMethod;
private final List<MethodInterceptor> interceptorList;
private int currentInterceptorIndex = -1;
public ReflectiveMethodInvocation(Object targetObject, Method targetMethod, List<MethodInterceptor> interceptorList) {
this.targetObject = targetObject;
this.targetMethod = targetMethod;
this.interceptorList = interceptorList;
}
@Override
public Object proceed() throws Throwable {
if (this.currentInterceptorIndex == this.interceptorList.size() - 1) {
return invokeJoinPoint();
}
this.currentInterceptorIndex++;
MethodInterceptor interceptor =
this.interceptorList.get(this.currentInterceptorIndex);
return interceptor.invoke(this);
}
private Object invokeJoinPoint() throws Throwable {
return this.targetMethod.invoke(this.targetObject);
}
}
NioCoderService
模擬service類
public class NioCoderService {
public void testAop() {
System.out.println("http://niocoder.com/");
}
}
TransactionManager
模擬通知類
public class TransactionManager {
public void start() {
System.out.println("start tx");
}
public void commit() {
System.out.println("commit tx");
}
public void rollback() {
System.out.println("rollback tx");
}
}
ReflectiveMethodInvocationTest
beforeAdvice->afterReturningAdvice
測試類,測試通知
public class ReflectiveMethodInvocationTest {
private AspectJBeforeAdvice beforeAdvice = null;
private AspectJAfterReturningAdvice afterReturningAdvice = null;
private NioCoderService nioCoderService;
private TransactionManager tx;
public void setUp() throws Exception {
nioCoderService = new NioCoderService();
tx = new TransactionManager();
beforeAdvice = new AspectJBeforeAdvice(TransactionManager.class.getMethod("start"), tx);
afterReturningAdvice = new AspectJAfterReturningAdvice(TransactionManager.class.getMethod("commit"), tx);
}
public void testMethodInvocation() throws Throwable {
Method method = NioCoderService.class.getMethod("testAop");
List<MethodInterceptor> interceptorList = new ArrayList<>();
interceptorList.add(beforeAdvice);
interceptorList.add(afterReturningAdvice);
ReflectiveMethodInvocation mi = new ReflectiveMethodInvocation(nioCoderService, method, interceptorList);
mi.proceed();
}
public static void main(String[] args) throws Throwable {
ReflectiveMethodInvocationTest reflectiveMethodInvocationTest = new ReflectiveMethodInvocationTest();
reflectiveMethodInvocationTest.setUp();
reflectiveMethodInvocationTest.testMethodInvocation();
}
}
輸出:
start tx
http://niocoder.com/
commit tx
時(shí)序圖 beforeAdvice->afterReturningAdvice


afterReturningAdvice->beforeAdvice
修改interceptorList的順序
public void testMethodInvocation() throws Throwable {
Method method = NioCoderService.class.getMethod("testAop");
List<MethodInterceptor> interceptorList = new ArrayList<>();
interceptorList.add(afterReturningAdvice);
interceptorList.add(beforeAdvice);
ReflectiveMethodInvocation mi = new ReflectiveMethodInvocation(nioCoderService, method, interceptorList);
mi.proceed();
}
輸出:
start tx
http://niocoder.com/
commit tx
時(shí)序圖 afterReturningAdvice->beforeAdvice


代碼下載
github:https://github.com/longfeizheng/data-structure-java/blob/master/src/main/java/cn/merryyou/aop
代碼下載
github:https://github.com/longfeizheng/data-structure-java
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
一分鐘掌握J(rèn)ava?ElasticJob分布式定時(shí)任務(wù)
ElasticJob?是面向互聯(lián)網(wǎng)生態(tài)和海量任務(wù)的分布式調(diào)度解決方案,本文主要通過簡單的示例帶大家深入了解ElasticJob分布式定時(shí)任務(wù)的相關(guān)知識,需要的可以參考一下2023-05-05
Spring中為bean指定InitMethod和DestroyMethod的執(zhí)行方法
在Spring中,那些組成應(yīng)用程序的主體及由Spring IoC容器所管理的對象,被稱之為bean,接下來通過本文給大家介紹Spring中為bean指定InitMethod和DestroyMethod的執(zhí)行方法,感興趣的朋友一起看看吧2021-11-11
如何將Java枚舉名稱作為注解的屬性值實(shí)現(xiàn)詳解
這篇文章主要為大家介紹了如何將Java枚舉名稱作為注解的屬性值實(shí)現(xiàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-05-05
Java函數(shù)式編程(十二):監(jiān)控文件修改
這篇文章主要介紹了Java函數(shù)式編程(十二):監(jiān)控文件修改,本文是系列文章的第12篇,其它文章請參閱本文底部的相關(guān)文章,需要的朋友可以參考下2014-09-09
Java通過Timer與TimerTask實(shí)現(xiàn)定時(shí)任務(wù)調(diào)度方式
本文介紹了如何在Java中使用`Timer`和`TimerTask`類來實(shí)現(xiàn)定時(shí)任務(wù)調(diào)度,`Timer`類用于創(chuàng)建計(jì)時(shí)器并安排任務(wù),而`TimerTask`類用于定義具體的任務(wù),文章詳細(xì)介紹了這兩個(gè)類的方法和使用示例,包括創(chuàng)建任務(wù)、安排任務(wù)、取消任務(wù)等操作,通過一個(gè)簡單的例子2024-12-12
java階乘計(jì)算獲得結(jié)果末尾0的個(gè)數(shù)代碼實(shí)現(xiàn)
今天偶然看到一個(gè)要求,求1000~10000之間的數(shù)n的階乘并計(jì)算所得的數(shù)n!末尾有多少個(gè)0?要求: 不計(jì)算 只要得到末尾有多少個(gè)0就可以了,看下面的代碼吧2013-12-12

