天天看點

JAVA AOP程式設計之動态代理技術

 java中的代理是什麼呢?

比如說我們用到一個類A ,我們往常的方法就是直接使用這個類A  ,這樣在大型的軟體開發中有很大的局限性、 。    我們對于使用的類A的修改隻能通過對源檔案寫死的修改,

代理就很好的突破了這個瓶頸。

在代理中我們可以定義一個類B,這個類B有個特點 就是和類A有着實作同樣的接口 ,我們在類B中間接的調用了 類A,  我們也可以向這個代理的類插入一些通告消息類 。

着在開發架構中經常用到 。

在JAVA中用于動态生成代理類的類 就是  java.lang.reflect.Proxy  這個類 具體的使用 可以去 看看有關于JDK的文檔 。   

在AOP的程式設計中,InvocationHandler 這個類是作為代理類對于target類的間接調用者 ,所有的被代理類都是通過 這個InvocationHandler這個類來進行調用的 。

我們在對這些步驟進行操作的時候 隻需要把實作過程封裝起來  把 需要代理的類 作為Object傳遞進去 那麼就可以實作 代理的通用化  ,于是一個小java架構就産生了 。

在使用的過程用 涉及到匿名内部類 ,這裡提到 在匿名内部類中調用外部的對象 需要 吧外面的對象 聲明為 final 。。。。 這是java的文法 為了是保證資料的安全性。。

StirngBuffer是一個線程安全的類,繼承了String在多線程中用到  。

如果隻涉及到 單線程那麼 就用 StringBuilder這個類 效率會提高很多。。

關于代理的結構圖如下:

JAVA AOP程式設計之動态代理技術

下面我寫一個例子來實作動态代理 :

package me.test;

import java.lang.reflect.Constructor;

import java.lang.reflect.InvocationHandler;

import java.lang.reflect.InvocationTargetException;

import java.lang.reflect.Method;

import java.lang.reflect.Proxy;

import java.util.ArrayList;

import java.util.Collection;

import java.lang.reflect.TypeVariable;

public class MyProxy

{    

 public static void main(String []args) throws IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException

 {

 Class  clazzProxy=Proxy.getProxyClass(Collection.class.getClassLoader(),Collection.class) ;        //利用Proxy類産生一份代理類的位元組碼

 //Create a  Dynamic  Class  by  using  Proxy  

 Constructor  constructors[]=clazzProxy.getConstructors()  ;   //獲得代理類的構造方法數組 反射原理

 Method []methods=clazzProxy.getMethods()  ;     //獲得代理類的方法

 System.out.println("Constructor List:"); 

 for(Constructor con:constructors) 

 {    

  String cons=con.getName() ;

  StringBuilder conBuilder=new StringBuilder(cons) ;

  Class []types = con.getParameterTypes()  ;

  conBuilder.append('(')  ;

     if(types.length!=0&&types!=null)

     {

      for(Class type:types)

      {

       conBuilder.append(type.getName())  ;

       conBuilder.append(',')  ;

      }

      conBuilder.deleteCharAt(conBuilder.lastIndexOf(",")) ;

     }  

  conBuilder.append(')') ;

     System.out.println(conBuilder);

 }

 System.out.println("Methoid list:");  

 for(Method med:methods) 

 {   

  String cons=med.getName() ;

  Class []types = med.getParameterTypes()  ;

 /////////////////////////////////////////////////////////////這裡是代理類的實作部分

 class  MyInvocationHandler implements InvocationHandler  

  @Override

  public Object invoke(Object proxy, Method method, Object[] args)                   

    throws Throwable {

   // TODO Auto-generated method stub

   return null;

  }

 Collection cn1=(Collection)constructors[0].newInstance((new MyInvocationHandler()))   ;    //生成一個代理類的對象 這個對象實作了 Collection接口

 System.out.println(cn1.toString());

 /*************************************************************************************/   

 Collection cn2=(Collection)constructors[0].newInstance(new InvocationHandler(){

  public Object invoke(Object proxy, Method method, Object[] args)

 })  ;

 /***************************************************************************************/

  final ArrayList list=new ArrayList() ;

    Advice adv=new MyAdvice() ;  //通告類 對象

  Collection cn3 = getProxy(list, adv);

   cn3.add("xiaowei")  ; //會調用 對于代理類的操作會調用InvocationHandler的invoke方法  進行調用目标類  ,調用方法如同反射 機制

   cn3.add("man")  ;

   cn3.add("軟體技術")  ;

   System.out.println("包含"+cn3.size()+"個元素!")  ;

   for(Object obj:cn3)

   {

    System.out.println(obj.toString());

   }

 private static Collection getProxy(final Object list ,final Advice advice) {

  Collection cn3=(Collection)Proxy.newProxyInstance(Collection.class.getClassLoader(),

    new Class[]{Collection.class},

    new InvocationHandler()

    /* @Override

     public Object invoke(Object proxy, Method method, Object[] args)  //代理類在執行每一個被代理類的方法的時候 就會調用這個invoke方法 并且傳遞Method對象 我們就可以動态的調用目的類的方法

       throws Throwable {

       // ArrayList list=new ArrayList() ;    //必須作為一個成員來實作 否則 每次進行插入操縱那麼調用的都是一個新的對象

       Long beginTime=System.currentTimeMillis()  ;

      Object returnVal= method.invoke(list, args);  //Invoke the Method 

       Long endTime=System.currentTimeMillis()  ; 

       System.out.println("Runtime="+(endTime-beginTime));   

       return  returnVal; 

     }*/  

    @Override

   public Object invoke(Object proxy, Method method, Object[] args)

     throws Throwable {

     // ArrayList list=new ArrayList() ;    //必須作為一個成員來實作 否則 每次進行插入操縱那麼調用的都是一個新的對象

    advice.beginRun(method) ;  //内部類調用外部的對象的時候 需要使用 final聲明 

    Object returnVal= method.invoke(list, args);  //Invoke the Method     執行代理傳遞過來的執行方法 

    advice.afterRun(method)  ;

     return  returnVal;   

   }

    );

  return cn3;

}

 //////////////////////////////////////////////////////////////////////////通告接口 和實作類

 package me.test;

public interface Advice

 public void beginRun(Method method) ;

 public void afterRun(Method method) ;

public class MyAdvice  implements Advice{

 long  beginTime   ;

 @Override

 public void beginRun(Method  method ) {

   beginTime=System.currentTimeMillis() ; 

 public void afterRun(Method  method) {

  long endTime=System.currentTimeMillis()   ;

  System.out.println(method.getName()+"運作了"+(endTime-beginTime)+"ms!");

 }