Spring AOP的實現:AOP基本概念
Spring AOP的概述
目錄
AOP的概念
AOP的概念: Aspect-Oriented Programming(面向切面程式設計)的簡稱。用來描述分散在物件,類或函式中的橫切面。
這也是為什麼我們稱它為面向切面程式設計,它是橫向的,就像在一個業務邏輯橫切一刀。對於它的某一個方法進行監控和加強一樣。從關注點中分離出橫切關注點是面向切面的程式設計的核心概念。可以通過預編譯和執行期動態代理的方式對我們的原始碼進行監控。使得業務邏輯的執行和效能的優化分離開,可以讓我們在編寫業務邏輯的時候專注於業務邏輯的實現,而將對於我們的業務邏輯的功能增強,例如日誌監控,交由其他代理類進行實現。這樣我們的業務邏輯程式碼中就不再含有針對特定領域問題程式碼的呼叫。我們的業務邏輯的維護工作就交給了我們的代理類來進行完成了。
既然說到了代理類,那麼我們就需要介紹一下AOP應用到了設計模式中代理模式
代理模式: 給某一個物件提供一個代理物件,代理物件控制了原物件的引用。就像一個人去代替另一個人去做一件事情,但是這個人可以對這件事情進行一定的監控和加強。通過對於代理模式的分析,我們可以推論出。它實際上和我們在Spring MVC中接觸到的攔截器很相似。攔截器攔截請求就如同代理物件執行相應的目標物件的方法。實際上對於目標物件的方法的執行交給了代理物件來執行。
舉個例子,如果我們登入一個網站。網站會根據我們的身份為我們提供不同的工作,我們可以在目標類中寫入如何進行登入驗證密碼,返回一個值。這個值是我們的身份標識,例如會員,普通使用者。這個時候代理類代理了我們的目標類並通過登入驗證獲取到了返回值,根據不同的返回值對我們的請求進行相應的加強。
現在我來介紹一下關於Spring AOP中的一些名詞概念。
1.連線點:業務邏輯中被攔截的點(SpringAOP中指的是方法)
2. 切點:匹配連線點的表示式,通過切點來設定那些連線點需要被攔截代理。
3. 切面:需要被攔截代理的連線點構成了一個切面。
4. 通知:AOP中對連線點進行代理時所進行的操作。
5. 目標物件:連線點所在的物件就是目標物件。
6. 代理物件:對目標物件進行代理的物件。
Java動態代理
那麼接下來我來演示一下關於Java動態代理機制的執行,這裡面涉及到了一個InvocationHandler介面,這個介面是非常關鍵的。實際上AOP的實現原理底層就是Java的動態代理機制。
首先我們來宣告一個介面
package com.xt.spring.context.aop.dynamic;
public interface Person {
public void run();
}
然後用一個Coder類來實現這個介面
package com.xt.spring.context.aop.dynamic;
public class Coder implements Person{
public void run() {
System.out.println("the coder is running");
}
}
接下里我聲明瞭一箇中介類,作為代理物件和目標物件的中介,它聲明瞭如何對目標物件的方法進行加強,同時它需要持有一個目標物件,這個中介類需要實現InvocationHandler介面並實現其中invoke方法。之後我們對於目標物件的方法呼叫實際上都是跳到這個最終的代理類的invoke方法中,通過反射的形式進行實現我們要加強的方法。
package com.xt.spring.context.aop.dynamic;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class ProxyTest implements InvocationHandler{
private Object obj;
public ProxyTest(Object obj){
this.obj = obj;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("方法執行前的時間: "+System.currentTimeMillis());
Object result = method.invoke(this.obj, args);
System.out.println("方法執行後的時間: "+System.currentTimeMillis());
return result;
}
}
接下來我們來對我們的程式碼進行測試
package com.xt.spring.context.aop.dynamic;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class MyTest {
public static void main(String[] args) {
Person person = new Coder();
InvocationHandler handler = new ProxyTest(person);
Person proxy = (Person)Proxy.newProxyInstance(person.getClass().getClassLoader(), person.getClass().getInterfaces(), handler);
proxy.run();
}
}
首先我們通過介面回撥宣告我們的person物件並交給我們中介類handler進行持有。
InvocationHandler handler = new ProxyTest(person);
接下來就是代理物件的生成過程了,這個過程實際上是很複雜的。主要由
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
完成,它需要一個類載入器,目標類實現的介面 ,以及一箇中間類指明如何對目標物件進行一個加強。
首先這個方法會為我們生成一個代理類,這個代理類就是根據java的動態代理原理將我們的目標物件的方法寫入到代理類中。在這個代理類會呼叫我們的handler中的invoke方法對相應的方法進行加強。當我們在此使用方法時,實際時就是通過這個代理物件來呼叫方法而不是通過最開始的person物件呼叫方法了。實際上通過對代理類的反編譯程式碼可以看出,底層的方法依舊呼叫了Invoke方法。
這就是java動態代理,它在aop的實現中起到了至關重要的作用。
Spring AOP程式碼舉例
關於Spring AOP程式碼的實現,我在這篇文章中進行了舉例