本文內容為我在網上搜集Spring AOP資料的彙總、摘抄。 AOP是一種編程思想,其對不同對象進行了橫向的抽象,將不同對象的、和主流程無關的公共邏輯抽象出來以方便維護。AOP的實現基礎為AOP動態代理,動態代理又可以由JDK動態代理和CGLIB實現。Spring中AOP的編程模型是定義組件、定義... ...
摘要
本文內容為我在網上搜集Spring AOP資料的彙總、摘抄。
AOP是一種編程思想,其對不同對象進行了橫向的抽象,將不同對象的、和主流程無關的公共邏輯抽象出來以方便維護。AOP的實現基礎為AOP動態代理,動態代理又可以由JDK動態代理和CGLIB實現。Spring中AOP的編程模型是定義組件、定義切入點、定義增強功能。
關鍵詞:Spring,AOP
一、AOP簡介
1. 什麼是AOP
AOP(Aspect Oriented Programming,面向切麵編程),橫向抽象的一種編程思想,是對OOP(Object Oriented Programming,面向對象編程)的補充和完善。
OOP中的基本三個基本特征:封裝、繼承、多態,其對象關係的描述是縱向的,對於分散在不同對象、同一層面的代碼卻無能為力。比如需要在代碼開頭和結尾處都列印相同的日誌,就沒有辦法描述這種業務了。
AOP則可以解決這個問題,它可以將不同代碼同一層次的業務無關的公共邏輯抽象出來,再把代碼邏輯織入到對應的切麵點,這樣就可以減少重覆代碼,以及方便維護了。
AOP的應用可以有許可權認證、日誌、事務等。
2. AOP的一些概念
概念 | 解釋 |
---|---|
核心關註點 | 業務處理的主要流程為核心關註點 |
橫切關註點 | 與業務處理主要流程不相關的部分為橫切關註點(特征:分散) |
切麵(aspect) | 切麵為對橫切關註點的抽象 |
連接點(joinpoint) | 被攔截的點,在Spring中為攔截到的方法 |
切入點(pointcut) | 對連接點進行攔截的定義 |
通知(adivce) | 指攔截到連接點後,要執行的代碼。可以分為:前置、後置、異常、最終、環繞 |
目標對象 | 代理的目標對象 |
織入(weave) | 將切麵應用到目標對象,產生代理對象的過程。(即將行為織入到業務流程中) |
引入(introduction) | 不修改代碼,在運行期(runtime)將類動態添加一些方法或欄位。 |
二、Spring中AOP的實現原理
Spring AOP實現的基石在於代理,也就是應用AOP後實際上是生成AOP代理對象,Spring中AOP代理及其依賴關係由IoC容器負責生成、管理。
代理對象=目標對象+切麵處理(通知)
1. 代理
1.1 靜態代理
靜態代理產生於代碼的編譯階段,一旦代碼運行就不可改變;
// 介面
public interface IPerson {
public void doSth();
}
// 介面實現
public class Person implements IPerson {
public void doSth(){
System.out.println("do sth");
}
}
// 代理實現
public class PersonProxy {
private IPerson person;
public PersonProxy(IPerson person) {
this.person = person;
}
public void doSth() {
System.out.println("before do sth");
person.doSth();
System.out.println("after do sth");
}
}
public static void main(String[] args) {
PersonProxy personProxy = new PersonProxy(new Person());
personProxy.doSth();
}
/*
result console:
before do sth
do sth
after do sth
*/
1.2 動態代理
這裡特指JDK動態代理,區別與靜態代理,動態代理產生於代碼的運行時階段。JDK動態代理利用了Java的反射機制,生成一個實現代理介面的類,調用具體方法由InvocationHandler來處理。這種動態代理需要依賴介面來實現。
public class PersonProxy implements InvocationHandler {
private Object delegate;
public Object bind(Object delegate) {
this.delegate = delegate;
// 指明類載入器、指明生成哪個對象的代理對象(介面指定)、指明Handler
return Proxy.newProxyInstance(delegate.getClass().getClassLoader(), delegate.getClass().getInterfaces(), this);
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null;
try {
System.out.println("before do sth");
result = method.invoke(delegate, args);
System.out.println("after do sth");
} catch(Exception e) {
throw e;
}
return result;
}
}
public static void main(String[] args) {
PersonProxy personProxy = new PersonProxy();
IPerson iPerson = (IPerson) personProxy.bind(new Person());
iPerson.doSth();
}
/*
result console:
before do sth
do sth
after do sth
*/
1.3 CGLIB
如果沒有介面,動態代理可以藉助CGLIB來實現,它可以用生成代理目標子類(因此不能代理final修飾的類)的方式來實現代理,而不是介面,規避來介面的局限性。
實現MethodInterceptor介面來實現。
public class PersonProxy implements MethodInterceptor {
private Object delegate;
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("before do sth");
Object result = methodProxy.invokeSuper(method, args);
System.out.println("after do sth");
return result;
}
public static Person getProxyInstance() {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(Person.class);
enhancer.setCallback(new PersonProxy());
return (Person) enhancer.create();
}
}
public static void main(String[] args) {
Person person = PersonProxy.getProxyInstance();
person.doSth();
}
/*
result console:
before do sth
do sth
after do sth
*/
2. Spring AOP代理創建規則
Spring提供了兩種方式來生成代理對象:JDKProxy和CGLIB
使用方式由AopProxyFactory根據AdvisedSupport對象配置來決定。
代理預設創建規則:
- 如果目標類是介面,則使用Java動態代理創建AOP代理;
- 如果目標類不是介面,則使用Cglib生成代理;
三、在Spring中使用AOP
AOP編程步驟:
- 定義普通業務組件;
- 定義切入點(切入點和業務組件的對應關係可以是一對多);
- 定義增強處理,即為普通業務組件織入的動作;
1. 使用XML文件配置AOP
2. 使用註解配置AOP
四、總結
- AOP(Aspect Oriented Programming,面向切麵編程),橫向抽象的一種編程思想,是對OOP(Object Oriented Programming,面向對象編程)的補充和完善。
- Spring AOP實現的基石在於代理,也就是應用AOP後實際上是生成AOP代理對象,Spring中AOP代理及其依賴關係由IoC容器負責生成、管理。
- Spring中AOP的編程模型是定義組件、定義切入點、定義增強功能。