1. 程式人生 > >Java程式設計師從笨鳥到菜鳥之(七十三)細談Spring(五)spring之AOP底層大揭祕

Java程式設計師從笨鳥到菜鳥之(七十三)細談Spring(五)spring之AOP底層大揭祕

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow

也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!

               

       眾所周知,java是面嚮物件語言的有力代表,提到java我們就會立即想到面向物件,提到面向物件我們就會想到java然而面向物件也並非完美無缺的,它更注重於物件層次結構方面的東西,對於如何更好的管理物件行為內部結構,還存在著些許不足。那麼我們如何使這個問題的得到更完美的解決呢?答案就是AOP

        AOPAspect-Oriented ProgrammingAOPOOP的補充,是GOF的延續。我們知道設計模式是對於面向物件設計中經驗的總結,它孜孜不斷追求的就是呼叫者與被呼叫者之間的解耦。有了設計模式我們可以更有效的利用面向物件的特性,使得整個軟體設計更加靈活、優雅。但是設計模式是基於面向物件的思想而形成的,更多的時候關注的是物件層次的東西,在解決物件行為內部問題方面卻有些不足。AOP的出現恰恰就是對面向物件思想做出了完美的補充。

     說到AOP,我們就不得不來提一下軟體的縱向和橫向問題。

從縱向結構來看就是我們軟體系統的各個模組,它主要負責處理我們的核心業務(例如商品訂購、購物車檢視);而從橫向結構來看,我們幾乎每個系統又包含一些公共模組(例如許可權、日誌模組等)。這些公共模組分佈於我們各個核心業務之中(例如訂購和檢視商品明細的過程都需要檢查使用者許可權、記錄系統日誌等)。這樣一來不僅在開發過程中要處處關注公共模組的處理而且開發後維護起來也是十分麻煩。而有了AOP之後將應用程式中的商業邏輯同對其提供支援的通用服務進行分離,使得開發人員可以更多的關注核心業務開發。 

                     


下面我們就以一個簡單的例子來看一下AOP吧!比如說,我們現在要開發的一個應用裡面有很多的業務方法,但是,我們現在要對這個方法的執行做全面監控,或部分監控.也許我們就會在要一些方法前去加上一條日誌記錄,我們寫個例子看看我們最簡單的解決方案
我們先寫一個介面IHello.java程式碼如下:

public interface IHello/** *//**  * 假設這是一個業務方法 *@param name */ void sayHello(String name); }


裡面有個方法,用於輸入"Hello" 加傳進來的姓名;我們去寫個類實現IHello介面


public class Helloimplements IHello{public void sayHello(String name){System.out.println("Hello" + name);}}


現在我們要為這個業務方法加上日誌記錄的業務 , 我們在不改變原始碼的情況下 , 我們會去怎麼做呢 ? 也許 , 你會去寫一個類去實現 IHello 介面 , 並依賴 Hello 這個類 . 程式碼如下 :

public class HelloProxyimplements IHelloprivate IHello hello;  public HelloProxy(IHello hello)this.hello= hello;  } public void sayHello(String name){ Logger.logging(Level.DEBUGE,"sayHello method start."); hello.sayHello(name); Logger.logging(Level.INFO,"sayHello method end!"); }}


      從上面的程式碼我們可以看出,hello物件是被HelloProxy這個所謂的代理態所建立的.這樣,如果我們以後要把日誌記錄的功能去掉.那我們只要把得到hello物件的的具體實現改為Hello的就可以。上面的程式碼 就是對AOP的最簡單的視線,但是我們接下來想,如果我們要在很多業務邏輯之前加日誌的話,那麼,我們是不是要去寫很多個HelloProxy這樣的類呢.沒錯,是的.其實也是一種很麻煩的事.jdk1.3以後.jdk跟我們提供了一個API java.lang.reflect.InvocationHandler的類這個類可以讓我們在JVM呼叫某個類的方法時動態的為些方法做些什麼事.讓我們把以上的程式碼改一下來看看效果.



同樣,我們寫一個IHello的介面和一個Hello的實現類.在介面中.我們定義兩個方法;程式碼如下 :

IHello.java

package sinosoft.dj.aop.proxyaop;  public interface IHello/** *//**  * 業務處理A方法  *@param name */ void sayHello(String name)/** *//** * 業務處理B方法 *@param name*/void sayGoogBye(String name);}




Hello.java

package sinosoft.dj.aop.proxyaop;  public class Helloimplements IHello{  public void sayHello(String name){  System.out.println("Hello" + name);  } public void sayGoogBye(String name){ System.out.println(name+" GoodBye!"); }}



我們一樣的去寫一個代理類.只不過.讓這個類去實現java.lang.reflect.InvocationHandler介面,程式碼如下:

package sinosoft.dj.aop.proxyaop;  import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method;import java.lang.reflect.Proxy;  public class DynaProxyHelloimplements InvocationHandler{  /** *//** * 要處理的物件(也就是我們要在方法的前後加上業務邏輯的物件,如例子中的Hello)*/private Object delegate;/** *//** * 動態生成方法被處理過後的物件 (寫法固定) * *@param delegate *@param proxy *@return*/public Object bind(Object delegate){this.delegate= delegate;return Proxy.newProxyInstance(this.delegate.getClass().getClassLoader(),this.delegate .getClass().getInterfaces(),this); }/** *//** * 要處理的物件中的每個方法會被此方法送去JVM呼叫,也就是說,要處理的物件的方法只能通過此方法呼叫 * 此方法是動態的,不是手動呼叫的*/public Object invoke(Object proxy, Method method, Object[] args)throws Throwable{ Object result= null;try {//執行原來的方法之前記錄日誌 Logger.logging(Level.DEBUGE, method.getName()+ " Method end .");//JVM通過這條語句執行原來的方法(反射機制) result= method.invoke(this.delegate, args);//執行原來的方法之後記錄日誌 Logger.logging(Level.INFO, method.getName()+ " Method Start!"); } catch (Exception e){ e.printStackTrace(); }//返回方法返回值給呼叫者 return result;} }



      從上面的例子我們看出.只要你是採用面向介面程式設計,那麼,你的任何物件的方法執行之前要加上記錄日誌的操作都是可以的.(DynaPoxyHello)自動去代理執行被代理物件(Hello)中的每一個方法,一個java.lang.reflect.InvocationHandler介面就把我們的代理物件和被代理物件解藕了

           

給我老師的人工智慧教程打call!http://blog.csdn.net/jiangjunshow

這裡寫圖片描述