歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

Spring AOP的實現原理

簡介

前段時間寫的java設計模式--代理模式,最近在看Spring Aop的時候,覺得於代理模式應該有密切的聯系,於是決定了解下Spring Aop的實現原理。

說起AOP就不得不說下OOP了,OOP中引入封裝、繼承和多態性等概念來建立一種對象層次結構,用以模擬公共行為的一個集合。但是,如果我們需要為部分對象引入公共部分的時候,OOP就會引入大量重復的代碼。例如:日志功能。

AOP技術利用一種稱為“橫切”的技術,解剖封裝的對象內部,並將那些影響了多個類的公共行為封裝到一個可重用模塊,這樣就能減少系統的重復代碼,降低模塊間的耦合度,並有利於未來的可操作性和可維護性。AOP把軟件系統分為兩個部分:核心關注點和橫切關注點。業務處理的主要流程是核心關注點,與之關系不大的部分是橫切關注點。橫切關注點的一個特點是,他們經常發生在核心關注點的多處,而各處都基本相似。比如權限認證、日志、事務處理。

實現原理

前面在學習代理模式的時候,了解到代理模式分為動態代理和靜態代理。現在我們就以代理模式為基礎先實現我們自己的AOP框架,再來研究Spring的AOP的實現原理。

先以靜態代理實現,靜態代理關鍵是在代理對象和目標對象實現共同的接口,並且代理對象持有目標對象的引用。

Spring AOP自定義注解方式實現日志管理 http://www.linuxidc.com/Linux/2015-11/125019.htm

Spring AOP進行日志記錄  http://www.linuxidc.com/Linux/2015-11/124731.htm

使用Spring AOP進行性能監控  http://www.linuxidc.com/Linux/2012-07/64681.htm

利用Spring AOP 更新Memcached 緩存策略的實現  http://www.linuxidc.com/Linux/2012-03/56503.htm

Spring AOP的兩種代理  http://www.linuxidc.com/Linux/2015-11/125017.htm

Spring AOP的注解實例 http://www.linuxidc.com/Linux/2015-11/125018.htm

公共接口代碼:

public interface IHello {
    /**
    * 業務方法
    * @param str
    */
    void sayHello(String str);
}

目標類代碼:

public class Hello implements IHello{
    @Override
    public void sayHello(String str) {
        System.out.println("hello "+str);
    }
   
}

代理類代碼,我們給它添加日志記錄功能,在方法開始前後執行特定的方法,是不是和AOP特別像呢?

public class ProxyHello implements IHello{   
    private IHello hello;   
    public ProxyHello(IHello hello) {
        super();
        this.hello = hello;
    }
    @Override
    public void sayHello(String str) {
        Logger.start();//添加特定的方法
        hello.sayHello(str);
        Logger.end();
    }

}

日志類代碼:

public class Logger {
    public static void start(){
        System.out.println(new Date()+ " say hello start...");
    }
   
    public static void end(){
        System.out.println(new Date()+ " say hello end");
    }
}

測試代碼:

public class Test {
    public static void main(String[] args) {
        IHello hello = new ProxyHello(new Hello());//如果我們需要日志功能,則使用代理類
        //IHello hello = new Hello();//如果我們不需要日志功能則使用目標類
        hello.sayHello("明天");   
    }
}

這樣我們就實現了一個最簡單的AOP,但是這樣會存在一個問題:如果我們像Hello這樣的類很多,那麼,我們是不是要去寫很多個HelloProxy這樣的類呢。其實也是一種很麻煩的事。在jdk1.3以後,jdk跟我們提供了一個API java.lang.reflect.InvocationHandler的類, 這個類可以讓我們在JVM調用某個類的方法時動態的為些方法做些什麼事。下面我們就來實現動態代理的實現。

動態代理實現主要是實現InvocationHandler,並且將目標對象注入到代理對象中,利用反射機制來執行目標對象的方法。

接口實現與靜態代理相同,代理類代碼:

public class DynaProxyHello implements InvocationHandler{
   
    private Object target;//目標對象
    /**
    * 通過反射來實例化目標對象
    * @param object
    * @return
    */
    public Object bind(Object object){
        this.target = object;
        return Proxy.newProxyInstance(this.target.getClass().getClassLoader(), this.target.getClass().getInterfaces(), this);
    }
   
    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        Object result = null;
        Logger.start();//添加額外的方法
        //通過反射機制來運行目標對象的方法
        result = method.invoke(this.target, args);
        Logger.end();
        return result;
    }
   
}

測試類代碼:

public class DynaTest {
    public static void main(String[] args) {
        IHello hello = (IHello) new DynaProxyHello().bind(new Hello());//如果我們需要日志功能,則使用代理類
        //IHello hello = new Hello();//如果我們不需要日志功能則使用目標類
        hello.sayHello("明天");
    }
}

更多詳情見請繼續閱讀下一頁的精彩內容: http://www.linuxidc.com/Linux/2016-04/129717p2.htm

Copyright © Linux教程網 All Rights Reserved