目錄
- AOP聯盟
-
- 1. Advice、MethodInterceptor攔截器(invoke方法:調用invocation.proceed)
- 2.Joinpoint 、MethodInvocation連接配接點(proceed方法:執行此攔截點)
- Spring AOP
-
- 1.Advice 通知-擴充接口(MethodBeforeAdvice、ThrowsAdvice、AfterReturningAdvice)
- 2.MethodInterceptor方法攔截器-擴充接口(對Advice的包裝)
- 3.MethodInvocation 方法調用連接配接點-擴充接口ProxyMethodInvocation、實作類ReflectiveMethodInvocation
- 4. Spring新增接口:Pointcut 切點
- 5. Spring新增接口:Advisor 通知器
- 總結
AOP聯盟是java對于AOP提供的一系列标準接口,頂層接口有:
Advice通知,及其繼承接口MethodInterceptor方法攔截器;
JointPoint連接配接點,及其繼承接口MethodInvocation。
Spring或其他具有AOP概念的架構都會依賴于此,從Spring擴充的接口來看,對于AOP的支援局限于方法的攔截。
比如Spring AOP中就實作了Advice的擴充接口:方法前置增強、方法後置增強、異常增強等;
另外還有對這些Advice的包裝實作:MethodInterceptor方法攔截器。
Spring中對于JoinPoint的實作包括了ProxyMethodInvocation,是AOP的核心類。
另外Spring新增了一個PointCut切點的概念,一個PointCut對應多個JointPoint。
在分析源碼實作之前,先來看一些基本概念與核心接口。
AOP聯盟
AOP Alliance 是java中對于面向切面提供了一系列标準化接口,Spring或其他具有AOP概念的架構會依賴這個包。
這個包中有兩個頂層接口:
- Advice:代表要織入的邏輯
- Joinpoint:連接配接點,增強邏輯的織入地點
1. Advice、MethodInterceptor攔截器(invoke方法:調用invocation.proceed)
Advice接口及其繼承接口:
- Advice:增強(通知),代表要織入的邏輯
- Interceptor:攔截器,代表了以攔截器方式去實作通知
- MethodInterceptor:方法攔截器(Spring中提供了實作類)
- ConstructorInterceptor:構造器攔截器
接口關系:
Advice
|
├── Interceptor
| |
| ├── MethodInterceptor
| ├── ConstructorInterceptor
接口方法:
(注意此處的MethodInterceptor是org.aopalliance.intercept.MethodInterceptor而非cglib包中的同名接口)
public interface Advice {
}
public interface Interceptor extends Advice {
}
//Spring中實作了此接口:MethodBeforeAdviceInterceptor、AfterReturningAdviceInterceptor等
public interface MethodInterceptor extends Interceptor {
//需要執行的時候,調用invocation.proceed()
Object invoke(MethodInvocation invocation) throws Throwable;
}
public interface ConstructorInterceptor extends Interceptor {
Object construct(ConstructorInvocation invocation) throws Throwable;
}
2.Joinpoint 、MethodInvocation連接配接點(proceed方法:執行此攔截點)
Joinpoint接口及其繼承接口:
- Joinpoint:連接配接點
- Invocation:調用連接配接點, 表示程式中的調用 ,是一個可以被攔截器攔截的連接配接點
- MethodInvocation:方法調用連接配接點(Spring中提供了實作類)
- ConstructorInvocation:構造器調用連接配接點
Joinpoint
|
├── Invocation
| |
| ├── MethodInvocation
| ├── ConstructorInvocation
接口方法:
(注意此處的Joinpoint是org.aopalliance.intercept.Joinpoint,而非指Spring中的org.aspectj.lang.JoinPoint)
public interface Joinpoint {
// 執行此攔截點,并進入到下一個連接配接點
Object proceed() throws Throwable;
// 傳回儲存目前連接配接點靜态部分的對象
Object getThis();
// 傳回此靜态連接配接點 一般就為目前的Method
AccessibleObject getStaticPart();
}
public interface Invocation extends Joinpoint {
// 獲得參數,如方法入參
Object[] getArguments();
}
//作為AOP Alliance中的底層接口,Spring AOP中實作了此接口:ReflectiveMethodInvocation
public interface MethodInvocation extends Invocation {
// 傳回目前被調用的Method
Method getMethod();
}
public interface ConstructorInvocation extends Invocation {
Constructor<?> getConstructor();
}
Spring AOP
Spring AOP并不是自立門戶,而是在AOP聯盟定義的一系列接口上,提供實作類或者進行封裝。
1.Advice 通知-擴充接口(MethodBeforeAdvice、ThrowsAdvice、AfterReturningAdvice)
Spring對于Advice接口繼承擴充:
- BeforeAdvice:前置增強
- AfterAdvice:後置增強
- MethodBeforeAdvice:方法前置增強
- AfterReturningAdvice:方法後置增強
- ThrowsAdvice:異常增強
Advice
|
├── Interceptor
| |
| ├── MethodInterceptor
| ├── ConstructorInterceptor
|
├── BeforeAdvice
| |
| ├── MethodBeforeAdvice
|
├── AfterAdvice
| |
| ├── ThrowsAdvice
| ├── AfterReturningAdvice
各個接口中方法:
public interface BeforeAdvice extends Advice {
}
public interface MethodBeforeAdvice extends BeforeAdvice {
void before(Method method, Object[] args, Object target) throws Throwable;
}
public interface AfterAdvice extends Advice {
}
public interface ThrowsAdvice extends AfterAdvice {
}
public interface AfterReturningAdvice extends AfterAdvice {
void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable;
}
2.MethodInterceptor方法攔截器-擴充接口(對Advice的包裝)
Spring中對于Advice接口繼承擴充:
- IntroductionInterceptor:引介增強,類級别的增強器
- MethodBeforeAdviceInterceptor
- AfterReturningAdviceInterceptor
- ThrowsAdviceInterceptor
- … …
Advice
|
├── Interceptor
| |
| ├── MethodInterceptor
| | |
| | ├── IntroductionInterceptor
| | ├── MethodBeforeAdviceInterceptor
| | ├── AfterReturningAdviceInterceptor
| | ├── ThrowsAdviceInterceptor
| ├── ConstructorInterceptor
|
├── BeforeAdvice
| |
| ├── MethodBeforeAdvice
|
├── AfterAdvice
| |
| ├── ThrowsAdvice
| ├── AfterReturningAdvice
接口方法,以MethodBeforeAdviceInterceptor為例:
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable {
private MethodBeforeAdvice advice;
// MethodBeforeAdviceInterceptor隻是将MethodBeforeAdvice進行了一個包裝
public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
Assert.notNull(advice, "Advice must not be null");
this.advice = advice;
}
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );
return mi.proceed();
}
}
同樣的,AfterReturningAdviceInterceptor是對AfterReturningAdvice的包裝、ThrowsAdviceInterceptor是對ThrowsAdvice的包裝。
3.MethodInvocation 方法調用連接配接點-擴充接口ProxyMethodInvocation、實作類ReflectiveMethodInvocation
Spring對于Joinpoint接口的繼承擴充:
- ProxyMethodInvocation:繼承自MethodInvocation接口,是Spring AOP的核心接口
- ReflectiveMethodInvocation:ProxyMethodInvocation的實作
Joinpoint
|
├── Invocation
| |
| ├── MethodInvocation
| | |
| | ├── ProxyMethodInvocation
| | | |
| | | ├── ReflectiveMethodInvocation
| ├── ConstructorInvocation
接口方法:
public interface ProxyMethodInvocation extends MethodInvocation {
Object getProxy();
MethodInvocation invocableClone();
MethodInvocation invocableClone(Object... arguments);
void setArguments(Object... arguments);
void setUserAttribute(String key, Object value);
Object getUserAttribute(String key);
}
4. Spring新增接口:Pointcut 切點
Pointcut是Spring AOP新增的接口,定義了Joinpoint連接配接點的比對規則,即:一個Pointcut對應多個Joinpoint,也就是 Advice邏輯織入的Joinpoint連接配接點的集合
接口定義如下
public interface Pointcut {
ClassFilter getClassFilter();
MethodMatcher getMethodMatcher();
Pointcut TRUE = TruePointcut.INSTANCE;
}
5. Spring新增接口:Advisor 通知器
Spring AOP新增了一個接口Advisor,用來包裝 Advice通知 和 Pointcut切點 兩個對象。
- Advisor:持有一個Advice
- PointcutAdvisor:在Advisor的基礎上,持有一個Pointcut
- IntroductionAdvisor:引介切面
Advisor
|
├── PointcutAdvisor
├── IntroductionAdvisor
接口方法:
public interface Advisor {
Advice getAdvice();
boolean isPerInstance();
}
public interface PointcutAdvisor extends Advisor {
Pointcut getPointcut();
}
public interface IntroductionAdvisor extends Advisor, IntroductionInfo {
ClassFilter getClassFilter();
void validateInterfaces() throws IllegalArgumentException;
}
總結
上述幾個概念之間的關系可以概括為
從Spring中所擴充的接口或者實作類來看,Spring 對 AOP 的支援局限于 方法的攔截。
(如果需求超過了簡單的方法調用,如構造器或屬性攔截,那麼需要考慮使用 AspectJ 來實作切面)