1. 程式人生 > >Java JDK代理、CGLIB、AspectJ代理分析比較

Java JDK代理、CGLIB、AspectJ代理分析比較

前言

什麼是代理,在Design patterns In java這個本書中是這樣描述的,簡單的說就是為某個物件提供一個代理,以控制對這個物件的訪問。在不修改原始碼的基礎上做方法增強,代理是一種設計模式,又簡單的分為兩種。

  • 靜態代理:代理類和委託類在程式碼執行前關係就確定了,也就是說在代理類的程式碼一開始就已經存在了。
  • 動態代理:動態代理類的位元組碼在程式執行時的時候生成。

靜態代理

先來看一個靜態代理的例子,Calculator是一個計算器的介面類,定義了一個加法的介面方法,由CalculatorImpl類實現真正的加法操作.現在如果我們想對這個方法做一層靜態的代理,這兒實現了一個簡單的代理類實現了計算介面Calculator,建構函式傳入的引數是真正的實現類,但是在呼叫這個代理類的add方法的時候我們在CalculatorImpl的實現方法執行的前後分別做了一些操作。這樣的代理方式就叫做靜態代理(可以理解成一個簡單的裝飾模式)。

很明顯靜態代理的缺點,由於我們需要事先實現代理類,那麼每個方法我都都需要去實現。如果我們要實現很多的代理類,那麼工作量就太大了。動態代理的產生就是這樣而來的。

public interface Calculator {
    //需要代理的介面
    public int add(int a,int b);
    //介面實現類,執行真正的a+b操作
    public static class CalculatorImpl implements Calculator{
        @Override
        public int add(int a, int b) {
            System.out.println("doing ");
            return a+b;
        }
    }
    //靜態代理類的實現.程式碼已經實現好了.
    public static class CalculatorProxy implements Calculator{
        private Calculator calculator;
        public CalculatorProxy(Calculator calculator) {
            this.calculator=calculator;
        }
        @Override
        public int add(int a, int b) {
            //執行一些操作
            System.out.println("begin ");
            int result = calculator.add(a, b);
            System.out.println("end ");
            return result;
        }
    }
}

動態代理

使用動態代理可以讓代理類在程式執行的時候生成代理類,我們只需要為一類代理寫一個具體的實現類就行了,所以實現動態代理要比靜態代理簡單許多,省了不少重複的工作。在JDK的方案中我們只需要這樣做可以實現動態代理了。

public class ProxyFactory implements InvocationHandler {
    private Class<?> target;
    private Object real;
    //委託類class
    public ProxyFactory(Class<?> target){
        this
.target=target; } //實際執行類bind public Object bind(Object real){ this.real=real; //利用JDK提供的Proxy實現動態代理 return Proxy.newProxyInstance(target.getClassLoader(),new Class[]{target},this); } @Override public Object invoke(Object o, Method method, Object[] args) throws Throwable { //代理環繞 System.out.println("begin"); //執行實際的方法 Object invoke = method.invoke(real, args); System.out.println("end"); return invoke; } public static void main(String[] args) { Calculator proxy =(Calculator) new ProxyFactory(Calculator.class).bind(new Calculator.CalculatorImpl()); proxy.add(1,2); } }

利用JDK的proxy實現代理動態代理,有幾個關鍵點,一個就是InvocationHandler介面,這個方法中的invoke方法是執行代理時會執行的方法。所以我們所有代理需要執行的邏輯都會寫在這裡面,invo引數裡面的method可以使用java 反射呼叫真實的實現類的方法,我們在這個方法周圍做一些代理邏輯工作就可以了。上面的程式碼會把Calculator介面的所有方法全部在程式執行時代理。不用我們一個個的去寫靜態代理的方法。

JDK動態代理的原理

先看Proxy.newProxyInstance(...)方法中的具體實現(省略大部分方法)。在下面的程式碼中會通過getProxyClass0(...)方法得到class物件,然後給把InvocationHandler已構造引數例項化代理物件。思路還是挺清晰的,但是如果要一探究竟我們還是得知道代理物件到底是什麼樣的,如何實現的代理呢?

public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)throws IllegalArgumentException
    {
    	//......
        /*
         *得到代理的物件的class物件。
         */
        Class<?> cl = getProxyClass0(loader, intfs);
        /*
         * 給class 物件建構函式傳入InvocationHandler 例項化物件
         */
         //.....
         return newInstance(cons, ih);
        //....
    }

getProxyClass0(..)方法中有下面這段程式碼.顧名思義這段程式碼應該是對代理的位元組碼做了快取.這是顯而易見的,我們不會每次呼叫都去生成代理物件。需要對代理物件快取。我們發現快取是用的一個叫WeakCache的類。我們不探究這個類具體的工作是怎樣的,我們只需要看我們的位元組碼是如何生成的.註釋中ProxyClassFactory這個類應該是我們需要尋找的類。

// If the proxy class defined by the given loader implementing
        // the given interfaces exists, this will simply return the cached copy;
        // otherwise, it will create the proxy class via the ProxyClassFactory
        return proxyClassCache.get(loader, interfaces);

從ProxyClassFactory中下面的方法可以看到具體生成位元組流的方法是ProxyGenerator.generateProxyClass(..).最後通過native方法生成Class物件。同時對class物件的包名稱有一些規定比如命名為com.meituan.Utils$proxy0。要想得到位元組碼例項我們需要先下載這部分位元組流,然後通過反編譯得到java程式碼。

if (proxyPkg == null) {
//包名稱,如com.meituan.com.Utils 用。分割
// if no non-public proxy interfaces, use com.sun.proxy package
         proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
    }
    /*
     * Choose a name for the proxy class to generate. proxyClassNamePrefix=`$proxy`  字首預設是包名稱加$proxy +自增的號碼
     */
    long num = nextUniqueNumber.getAndIncrement();
    String proxyName = proxyPkg + proxyClassNamePrefix + num;
    byte[] proxyClassFile = ProxyGenerator.generateProxyClass(proxyName, interfaces);
    //native 方法
return defineClass0(loader, proxyName,proxyClassFile, 0, proxyClassFile.length);

ProxyGenerator.generateProxyClass(..)方法生成位元組流,然後寫進硬碟.假設我把proxyName定義為Calcultor$ProxyCode.我們先在https://bitbucket.org/mstrobel/procyon/downloads 下載一個反編譯的jar包。然後執行下面的程式碼,我們得到了一個Calcultor$ProxyCode.class的檔案.然後在目錄下使用命令java -jar procyon-decompiler-0.5.29.jar Calcultor$ProxyCode.class 就能得到Calcultor$ProxyCode.java檔案。 當然也可以實現線上反編譯http://javare.cn/網站反編譯然後下載檔案

public static void main(String[] args) {
 		//傳入Calculator介面
        ProxyUtils.generateClassFile(Calculator.class,"Calcultor$ProxyCode");
}
 public static void generateClassFile(Class clazz,String proxyName)
    {
        //根據類資訊和提供的代理類名稱,生成位元組碼
        byte[] classFile = ProxyGenerator.generateProxyClass(proxyName,new Class[]{clazz});
        String paths = clazz.getResource(".").getPath();  
        System.out.println(paths);  
        FileOutputStream out = null;     
       
        //保留到硬碟中  
        out = new FileOutputStream(paths+proxyName+".class");    
        out.write(classFile);    
        out.flush();    
     	//...

下面的程式碼是就是反編譯過來的Calcultor$ProxyCode類。可以發現這個類實現了我們需要代理的介面Calculator。且他的建構函式確實是需要傳遞一個InvocationHandler物件,那麼現在的情況就是我們的生成了一個代理類,這個代理類是我們需要代理的介面的實現類。我們的介面中定義了add和reduce方法,在這個代理類中幫我們實現了,並且全部變成了final的。同時覆蓋了一些Object類中的方法。那我們現在以reduce這個方法舉例,方法中會呼叫InvocationHandler類中的invoke方法(也就是我們實現的邏輯的地方)。同時把自己的Method物件,引數列表等傳入進去。

public final class Calcultor$ProxyCode extends Proxy implements Calculator {
    private static Method m1;
    private static Method m4;
    private static Method m0;
    private static Method m3;
    private static Method m2;

    public Calcultor$ProxyCode(InvocationHandler var1) throws  {
        super(var1);
    }

    public final boolean equals(Object var1) throws  {
        try {
            return ((Boolean)super.h.invoke(this, m1, new Object[]{var1})).booleanValue();
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

    public final int reduce(int var1, int var2) throws  {
        try {
            return ((Integer)super.h.invoke(this, m4, new Object[]{Integer.valueOf(var1), Integer.valueOf(var2)})).intValue();
        } catch (RuntimeException | Error var4) {
            throw var4;
        } catch (Throwable var5) {
            throw new UndeclaredThrowableException(var5);
        }
    }

    public final int hashCode() throws  {
        try {
            return ((Integer)super.h.invoke(this, m0, (Object[])null)).intValue();
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final int add(int var1, int var2) throws  {
        try {
            return ((Integer)super.h.invoke(this, m3, new Object[]{Integer.valueOf(var1), Integer.valueOf(var2)})).intValue();
        } catch (RuntimeException | Error var4) {
            throw var4;
        } catch (Throwable var5) {
            throw new UndeclaredThrowableException(var5);
        }
    }

    public final String toString() throws  {
        try {
            return (String)super.h.invoke(this, m2, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    static {
        try {
        	//static靜態塊載入每個方法的Method物件
            m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[]{Class.forName("java.lang.Object")});
            m4 = Class.forName("jdkproxy.Calculator").getMethod("reduce", new Class[]{Integer.TYPE, Integer.TYPE});
            m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
            m3 = Class.forName("jdkproxy.Calculator").getMethod("add", new Class[]{Integer.TYPE, Integer.TYPE});
            m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}

JDK動態代理小結

現在我們對JDK代理有個簡單的原始碼級別的認識,理清楚一下思路:JDK會幫我們在執行時生成一個代理類,這個代理類實際上就是我們需要代理的介面的實現類。實現的方法裡面會呼叫InvocationHandler類中的invoke方法,並且同時傳入自身被呼叫的方法的的Method物件和引數列表方便我們編碼實現方法的呼叫。比如我們呼叫reduce方法,那麼我們就可以通過Method.Invoke(Object obj, Object... args)呼叫我們具體的實現類,再在周圍做一些代理做的事兒。就實現了動態代理。我們對JDK的特性做一些簡單的認識:

  • JDK動態代理只能代理有介面的類,並且是能代理介面方法,不能代理一般的類中的方法
  • 提供了一個使用InvocationHandler作為引數的構造方法。在代理類中做一層包裝,業務邏輯在invoke方法中實現
  • 重寫了Object類的equals、hashCode、toString,它們都只是簡單的呼叫了InvocationHandler的invoke方法,即可以對其進行特殊的操作,也就是說JDK的動態代理還可以代理上述三個方法
  • 在invoke方法中我們甚至可以不用Method.invoke方法呼叫實現類就返回。這種方式常常用在RPC框架中,在invoke方法中發起通訊呼叫遠端的介面等

CGLIB代理

JDK中提供的生成動態代理類的機制有個鮮明的特點是:某個類必須有實現的介面,而生成的代理類也只能代理某個類介面定義的方法。那麼如果一個類沒有實現介面怎麼辦呢?這就有CGLIB的誕生了,前面說的JDK的代理類的實現方式是實現相關的介面成為介面的實現類,那麼我們自然而然的可以想到用繼承的方式實現相關的代理類。CGLIB就是這樣做的。一個簡單的CGLIB代理是這樣實現的:

Enhancer enhancer=new Enhancer();
enhancer.setSuperclass(Calculator.class);
enhancer.setCallback(new MethodInterceptor() {
            //類似invokerhanddler的invoke方法
            @Override
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                System.out.println("begin");
                Object invoke = methodProxy.invoke(new Calculator.CalculatorImpl(), objects);
                System.out.println("end");
                return invoke;
            }
});
Calculator proxy =(Calculator) enhancer.create();
proxy.add(1,2);

CGLIB代理原理分析

通過在執行動態代理的程式碼前面加上一行程式碼就可以得到生成的代理物件.代理物件的class檔案會生成在你定義的路徑下。類似Calculator$CalculatorImpl$$EnhancerByCGLIB$$58419779.class這樣結構。

System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "${your path}");

之後我們通過反編譯得到反編譯後的java檔案。就上面的例子而言我們傳入的superclass是一個介面,並不是實現類。那我們得到的代理類會長成這樣:

//如果是介面代理類還是通過實現介面的方式
public class Calculator$$EnhancerByCGLIB$$40fd3cad implements Calculator, Factory{
//...
}

如果傳入的並不是介面,而是實現類的話,就會得到下面的代理類:

//如果是普通的類,會採用繼承的方式實現
public class Calculator$CalculatorImpl$$EnhancerByCGLIB$$58419779 extends CalculatorImpl implements Factory {
//...
}

但是不管是傳入的介面還是傳入的代理類,程式碼的實體都是長得差不多的:

ublic class Calculator$CalculatorImpl$$EnhancerByCGLIB$$2849428a extends CalculatorImpl implements Factory {

   private boolean CGLIB$BOUND;
   private static final ThreadLocal CGLIB$THREAD_CALLBACKS;
   private static final Callback[] CGLIB$STATIC_CALLBACKS;
   private MethodInterceptor CGLIB$CALLBACK_0;
   private InvocationHandler CGLIB$CALLBACK_1;
   private static final Method CGLIB$say4$1$Method;
   private static final MethodProxy CGLIB$say4$1$Proxy;
   private static final Object[] CGLIB$emptyArgs;
   private static final Method CGLIB$reduce$2$Method;
   private static final MethodProxy CGLIB$reduce$2$Proxy;
   private static final Method CGLIB$finalize$3$Method;
   private static final MethodProxy CGLIB$finalize$3$Proxy;
 	//省略 clone等  定義

	//初始化
   static void CGLIB$STATICHOOK1() {
      CGLIB$THREAD_CALLBACKS = new ThreadLocal();
      CGLIB$emptyArgs = new Object[0];
      Class var0 = Class.forName("jdkproxy.Calculator$CalculatorImpl$$EnhancerByCGLIB$$2849428a");
      Class var1;
      Method[] var10000 = ReflectUtils.findMethods(new String[]{"say4", "()V", "reduce", "(II)I"}, (var1 = Class.forName("jdkproxy.Calculator$CalculatorImpl")).getDeclaredMethods());
      CGLIB$say4$1$Method = var10000[0];
      CGLIB$say4$1$Proxy = MethodProxy.create(var1, var0, "()V", "say4", "CGLIB$say4$1");
      CGLIB$reduce$2$Method = var10000[1];
      CGLIB$reduce$2$Proxy = MethodProxy.create(var1, var0, "(II)I", "reduce", "CGLIB$reduce$2");
      var10000 = ReflectUtils.findMethods(new String[]{"finalize", "()V", "equals", "(Ljava/lang/Object;)Z", "toString", "()Ljava/lang/String;", "hashCode", "()I", "clone", "()Ljava/lang/Object;"}, (var1 = Class.forName("java.lang.Object")).getDeclaredMethods());
      CGLIB$finalize$3$Method = var10000[0];
      CGLIB$finalize$3$Proxy = MethodProxy.create(var1, var0, "()V", "finalize", "CGLIB$finalize$3");
      CGLIB$equals$4$Method = var10000[1];
      CGLIB$equals$4$Proxy = MethodProxy.create(var1, var0, "(Ljava/lang/Object;)Z", "equals", "CGLIB$equals$4");
      CGLIB$toString$5$Method = var10000[2];
      CGLIB$toString$5$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/String;", "toString", "CGLIB$toString$5");
      CGLIB$hashCode$6$Method = var10000[3];
      CGLIB$hashCode$6$Proxy = MethodProxy.create(var1, var0, "()I", "hashCode", "CGLIB$hashCode$6");
      CGLIB$clone$7$Method = var10000[4];
      CGLIB$clone$7$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/Object;", "clone", "CGLIB$clone$7");
      CGLIB$add$0 = Class.forName("jdkproxy.Calculator$CalculatorImpl").getDeclaredMethod("add", new Class[]{Integer.TYPE, Integer.TYPE});
   }
	//非介面中的方法,在實現類中定義的
   final void CGLIB$say4$1() {
      super.say4();
   }

   public final void say4() {
      MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
      if(this.CGLIB$CALLBACK_0 == null) {
         CGLIB$BIND_CALLBACKS(this);
         var10000 = this.CGLIB$CALLBACK_0;
      }

      if(var10000 != null) {
         var10000.intercept(this, CGLIB$say4$1$Method, CGLIB$emptyArgs, CGLIB$say4$1$Proxy);
      } else {
         super.say4();
      }
   }
	//繫結MethodInterceptor callback的方法會額外實現一個和原方法一模一樣的方法
   final int CGLIB$reduce$2(int var1, int var2) {
      return super.reduce(var1, var2);
   }

   public final int reduce(int var1, int var2) {
      MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
      if(this.CGLIB$CALLBACK_0 == null) {
         CGLIB$BIND_CALLBACKS(this);
         var10000 = this.CGLIB$CALLBACK_0;
      }

      if(var10000 != null) {
      //呼叫MethodInterceptor中的intercept方法
         Object var3 = var10000.intercept(this, CGLIB$reduce$2$Method, new Object[]{new Integer(var1), new Integer(var2)}, CGLIB$reduce$2$Proxy);
         return var3 == null?0:((Number)var3).intValue();
      } else {
         return super.reduce(var1, var2);
      }
   }

   final void CGLIB$finalize$3() throws Throwable {
      super.finalize();
   }

   protected final void finalize() throws Throwable {
      MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
      if(this.CGLIB$CALLBACK_0 == null) {
         CGLIB$BIND_CALLBACKS(this);
         var10000 = this.CGLIB$CALLBACK_0;
      }

      if(var10000 != null) {
         var10000.intercept(this, CGLIB$finalize$3$Method, CGLIB$emptyArgs, CGLIB$finalize$3$Proxy);
      } else {
         super.finalize();
      }
   }
	//省略 clone等
	
	//得到MethodProxy物件
   public static MethodProxy CGLIB$findMethodProxy(Signature var0) {
      String var10000 = var0.toString();
      switch(var10000.hashCode()) {
      case -1574182249:
         if(var10000.equals("finalize()V")) {
            return CGLIB$finalize$3$Proxy;
         }
         break;
     	//省略
           }

      return null;
   }

   public final int add(int var1, int var2) {
      try {
         InvocationHandler var10000 = this.CGLIB$CALLBACK_1;
         if(this.CGLIB$CALLBACK_1 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_1;
         }
			//呼叫invokeHandler中的invoke方法
         return ((Number)var10000.invoke(this, CGLIB$add$0, new Object[]{new Integer(var1), new Integer(var2)})).intValue();
      } catch (Error | RuntimeException var3) {
         throw var3;
      } catch (Throwable var4) {
         throw new UndeclaredThrowableException(var4);
      }
   }
	//...   
	//為每個方法繫結callback 根據實現fitler的不同會載入不同的callback
   private static final void CGLIB$BIND_CALLBACKS(Object var0) {
      Calculator$CalculatorImpl$$EnhancerByCGLIB$$2849428a var1 = (Calculator$CalculatorImpl$$EnhancerByCGLIB$$2849428a)var0;
      if(!var1.CGLIB$BOUND) {
         var1.CGLIB$BOUND = true;
         Object var10000 = CGLIB$THREAD_CALLBACKS.get();
         if(var10000 == null) {
            var10000 = CGLIB$STATIC_CALLBACKS;
            if(CGLIB$STATIC_CALLBACKS == null) {
               return;
            }
         }

         Callback[] var10001 = (Callback[])var10000;
         var1.CGLIB$CALLBACK_1 = (InvocationHandler)((Callback[])var10000)[1];
         var1.CGLIB$CALLBACK_0 = (MethodInterceptor)var10001[0];
      }

   }

   public void setCallback(int var1, Callback var2) {
      switch(var1) {
      case 0:
         this.CGLIB$CALLBACK_0 = (MethodInterceptor)var2;
         break;
      case 1:
         this.CGLIB$CALLBACK_1 = (InvocationHandler)var2;
      }

   }

   public Callback[] getCallbacks() {
      CGLIB$BIND_CALLBACKS(this);
      return new Callback[]{this.CGLIB$CALLBACK_0, this.CGLIB$CALLBACK_1};
   }
	//初始化我們定義的 callback 
   public void setCallbacks(Callback[] var1) {
      this.CGLIB$CALLBACK_0 = (MethodInterceptor)var1[0];
      this.CGLIB$CALLBACK_1 = (InvocationHandler)var1[1];
   }

   static {
      CGLIB$STATICHOOK1();
   }
}

上面這一份程式碼整個代理的流程彷彿是差不多的,都是在呼叫方法的時候router到InvokeHandler或者MethodInterceptor。為什麼會有兩種呢,因為CGLIB提供了filter的機制,可以讓不同的方法代理到不同的callback中,如下面這樣:


            
           

相關推薦

Java JDK代理CGLIBAspectJ代理分析比較

前言 什麼是代理,在Design patterns In java這個本書中是這樣描述的,簡單的說就是為某個物件提供一個代理,以控制對這個物件的訪問。在不修改原始碼的基礎上做方法增強,代理是一種設計模式,又簡單的分為兩種。 靜態代理:代理類和委託類在程式碼執行前關係就確

Spring 學習筆記(六)AOP 之思想概念和作用JDK代理Cglib子類代理

概念 AOP為Aspect Oriented Programming的縮寫,意味:面向切面程式設計。 與IOC一樣,是一種思想。 作用 對業務邏輯進行分離,降低耦合度,提高程式的重用性,提高開發效率。 JDK動態代理(介面代理) 弱點:JDK動態代理

JDKCGLibJavassist實現動態代理

一、類載入1.類載入過程模擬(先明白類載入過程,方可模擬類執行期間載入-建立代理類,呼叫目標方法)public class Programmer { public void code() { System.out.println("I'm a Prog

三種實現動態代理方式(jdkcglibjavaassist)

在編寫程式與實現某些功能時,我們經常會使用到動態代理。動態代理是個很簡單但是很有效的東西。在我們平時使用的框架中,像servlet的filter、包括spring提供的aop以及struts2的攔截器都使用了動態代理功能。我們日常看到的mybatis分頁外掛,以及日誌攔截、

動態代理CGlibAOP

Java 代理模式實現方式,主要有如下五種方法 靜態代理,工程師編輯代理類程式碼,實現代理模式;在編譯期就生成了代理類。 基於 JDK 實現動態代理,通過jdk提供的工具方法Proxy.newProxyInstance動態構建全新的代理類(繼承Proxy類,並持有Invoc

Spring AOP 代理實現的兩種方式: JDK動態代理Cglib框架動態代理

1.JDK動態代理 JDK API 內建 ---- 通過 Proxy類,為目標物件建立代理 (必須面向介面代理 ),此文中介面為UserDao,實現類為UserDaoImpl. public class UserDaoImpl implements UserDao {

細說java動態代理cglib的動態代理

          提到代理,想必大家對設計模式中的靜態代理和動態代理都比較熟悉,小編之前在部落格中對動態和靜態代理進行了對比,這篇博文就只探討java動態代理和cglib動態代理之間的區別; ♚  

簡單瞭解靜態代理JDK提供的動態代理cglib的動態代理

開發十年,就只剩下這套架構體系了! >>>   

Hybrid APP基礎篇(二)->NativeHybridReact NativeWeb App方案的分析比較

說明 Native、Hybrid、React、Web App方案的分析比較 目錄 前言 參考來源 前人栽樹,後臺乘涼,本文參考了以下來源 前置技術要求 閱讀本文前,建議先閱讀以下文章 楔子 目前的主流應用程式有四大型別:Native App、Hybrid App、React

Spring AOP 前篇(一):Java代理JDK靜態代理JDK動態代理CGLIB動態代理

Spring AOP 前篇:Java代理之JDK靜態代理、JDK動態代理、CGLIB動態代理 該文章參考多篇文章的基礎上進行了簡化並做少許修改,方便理解。原文章地址如下: Java之代理(jdk靜態代理,jdk動態代理,cglib動態代理,aop,aspectj

Java動態代理(JDKCGLIBJavassistASM之間的差別)

import com.foo.proxy.Rechargable;   import com.foo.proxy.Vehicle;   import java.lang.reflect.InvocationHandler;   import java.lang.reflect.Method;   im

Java中的靜態代理JDK動態代理cglib動態代理

一、靜態代理 代理模式是常用設計模式的一種,我們在軟體設計時常用的代理一般是指靜態代理,也就是在程式碼中顯式指定的代理。 靜態代理由業務實現類、業務代理類兩部分組成。業務實現類負責實現主要的業務方法,業務代理類負責對呼叫的業務方法作攔截、過濾、預處理。在需要呼叫

Java JDK中的靜態代理動態代理&Cglib動態代理

代理模式 代理模式是常用的java設計模式,他的特徵是代理類與委託類有同樣的介面,代理類主要負責為委託 類預處理訊息、過濾訊息、把訊息轉發給委託類,以及事後處理訊息等。代理類與委託類之間通常會存在關聯關係,一個代理類的物件與一個委託類的物件關聯,代理類的物件本

【轉載】Spring AOP詳解 JDK動態代理CGLib動態代理

rto 工廠 第一個 lec 僅支持 sel clas sleep gpo 原文地址:https://www.cnblogs.com/kukudelaomao/p/5897893.html AOP是Aspect Oriented Programing的簡稱,面向切面

java 代理模式(靜態代理動態代理Cglib代理) 轉載

cas 代理人 缺點 intercept 必須 lan itcast 技術 有時 Java的三種代理模式 1.代理模式 代理(Proxy)是一種設計模式,提供了對目標對象另外的訪問方式;即通過代理對象訪問目標對象.這樣做的好處是:可以在目標對象實現的基礎上,增強額外的功能操

03動態代理--JDK動態代理CGLib動態代理的組合實例

listen -- offer pri eth err imp instance music package com.offer.note.Java基礎.動態代理.CGLib引入增強; public interface Browser { void visitI

JDK靜態代理JDK動態代理以及CGLIB動態代理

這裡轉載兩篇好文章:“深入理解JDK動態代理機制” ,深入理解CGLIB動態代理機制 : https://www.jianshu.com/p/471c80a7e831 https://www.jianshu.com/p/9a61af393e41?from=timeline&isapp

《設計模式》之一文帶你理解單例JDK動態代理CGLIB動態代理靜態代理

個人認為我在動態代理方面的分析算是比較深入了,下次更新再修改一下,爭取做到最好,後續還有建造者模式、模板方法、介面卡、外觀、責任鏈、策略和原型模式的深入!各位讀者如果覺得還不錯的可以持續關注哦。謝謝各位!!! 我的github,到時上傳例子程式碼 https://github.com

java基礎-代理(靜態代理動態代理cglib代理

代理(Proxy)是一種設計模式,提供了對目標物件另外的訪問方式;即通過代理物件訪問目標物件.這樣做的好處是:可以在目標物件實現的基礎上,增強額外的功能操作,即擴充套件目標物件的功能. 這裡使用到程式設計中的一個思想:不要隨意去修改別人已經寫好的程式碼或者方法,如果需改修改

分享知識-快樂自己:三種代理(靜態JDKCGlib 代理

 1):代理模式(靜態代理)點我下載三種模式原始碼 代理模式是常用設計模式的一種,我們在軟體設計時常用的代理一般是指靜態代理,也就是在程式碼中顯式指定的代理。 靜態代理由 業務實現類、業務代理類 兩部分組成。 業務實現類 負責實現主要的業務方法,業務代理類負責對呼叫的業務方法作攔截、過濾、