1. AOP的核心概念
- 切面(Aspect):似于 Java 中的類聲明,常用于應(yīng)用中配置事務(wù)或者日志管理。一般使用 @Aspect 注解或者 <aop:aspect> 來(lái)定義一個(gè)切面。
- 連接點(diǎn)(Join Point):程序執(zhí)行中的特定點(diǎn),比如方法執(zhí)行、處理一個(gè)異常等。
- 切點(diǎn)(Pointcut):通過(guò)一種規(guī)則匹配的正則表達(dá)式,當(dāng)有連接點(diǎn)可以匹配到切點(diǎn)時(shí),就會(huì)觸發(fā)改切點(diǎn)相關(guān)聯(lián)的指定通知。
- 通知(Advice):在切面中某個(gè)連接點(diǎn)采取的動(dòng)作,通知方式也有5種:
- around(環(huán)繞通知):前后都加
- before(前置通知)
- after(后置通知)
- exception(異常通知)
- return(返回通知)
- 織入(Weaving):鏈接切面和目標(biāo)對(duì)象創(chuàng)建一個(gè)通知對(duì)象的過(guò)程。
AOP其實(shí)就是一種編程思想,而這上面的這個(gè)點(diǎn)就是編程的具體實(shí)現(xiàn)規(guī)范。
一個(gè)應(yīng)用中可以有多種通知方式所以在AOP中引入一種設(shè)計(jì)模式責(zé)任鏈模式通過(guò)這這種模式來(lái)順序執(zhí)行每一個(gè)通知當(dāng)然也可以使用@Order注解,配置數(shù)字越小,越先執(zhí)行。
2. AOP的執(zhí)行過(guò)程
準(zhǔn)備demo
@Component
public class AopTest {
public void log(){
System.out.println("正常執(zhí)行方法。。。。。。。。。。。");
}
}
@Component
@Aspect
public class AspectTest {
@Pointcut("execution(* com.test.*.service.AopTest.*(..))")
public void pointLog(){
}
@Before("pointLog()")
public void before(){
System.out.println("執(zhí)行方法之前。。。。。。before");
}
@After("pointLog()")
public void after(){
System.out.println("執(zhí)行方法之后。。。。。。after");
}
}

進(jìn)入到DynamicAdvisedInterceptor 這個(gè)靜態(tài)內(nèi)部類中的intercept方法。
private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {
@Override
@Nullable
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
。。。
// 從advised中 獲取配置好的AOP的通知方法
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
Object retVal;
//如果沒有通知方法則調(diào)用target對(duì)象的方法,顯然chain不為空則走else邏輯
if (chain.isEmpty() && CglibMethodInvocation.isMethodProxyCompatible(method)) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
try {
retVal = methodProxy.invoke(target, argsToUse);
}
catch (CodeGenerationException ex) {
CglibMethodInvocation.logFastClassGenerationFailure(method);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
}
else {
//通過(guò)CglibMethodInvocation來(lái)啟動(dòng)advice通知,proceed()通過(guò)調(diào)用super.proceed();
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
}
retVal = processReturnType(proxy, target, method, retVal);
return retVal;
}
。。。
}
}
進(jìn)入到ReflectiveMethodInvocation 中的proceed()方法
public class ReflectiveMethodInvocation implements ProxyMethodInvocation, Cloneable {
。。。
/**
* Index from 0 of the current interceptor we're invoking.
* -1 until we invoke: then the current interceptor.
*/
private int currentInterceptorIndex = -1;
// 省略其他的方法
@Override
@Nullable
public Object proceed() throws Throwable {
// 從索引為-1的攔截器開始調(diào)用,并且按順序遞增,如果整個(gè)List chain中調(diào)用完畢,則開始調(diào)用target的函數(shù)
// 具體的實(shí)現(xiàn)方式在AOPUtils.invokeJoinpointUsingRefection方法中,其實(shí)就是通過(guò)反射實(shí)現(xiàn)目標(biāo)方法
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
// 獲取下一個(gè)需要執(zhí)行的攔截器,沿著定義好的interceptorOrInterceptionAdvice的鏈進(jìn)行處理
//在new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed()時(shí),
//已經(jīng)將通知方法傳入到interceptorsAndDynamicMethodMatchers中。
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
// 對(duì)攔截器進(jìn)行動(dòng)態(tài)匹配,如果和定義的pointcut匹配 則就會(huì)執(zhí)行當(dāng)前的這個(gè)advice
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
return proceed();
}
}
else {
//普通攔截器,直接調(diào)用攔截器,將當(dāng)前的this(CglibMethodInvocation)作為參數(shù)保證當(dāng)前實(shí)例中調(diào)用鏈的執(zhí)行
//這里就利用到了責(zé)任鏈模式,進(jìn)行循環(huán)調(diào)用,直到所有通知執(zhí)行完成
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
}
Spring中的五種通知,首先是通過(guò)具Spring容器的啟動(dòng)過(guò)程獲取到具體的通知,在調(diào)用對(duì)象時(shí),通過(guò)動(dòng)態(tài)代理ASM技術(shù),把需要執(zhí)行的advice先全部放在一個(gè)chain對(duì)象的集合中,為了保證整個(gè)鏈的調(diào)用默認(rèn)會(huì)先調(diào)用ExposeInvocationInterceptor去觸發(fā)整個(gè)鏈?zhǔn)綀?zhí)行,在執(zhí)行完每一個(gè)advice時(shí)后都會(huì)再次回到super的proceed方法中,執(zhí)行下一個(gè)advice,在執(zhí)行不同的advice時(shí)有對(duì)應(yīng)的切面通知方法,當(dāng)所有的advice執(zhí)行完畢再通過(guò)cglib的FastClass機(jī)制調(diào)用目標(biāo)方法