動態代理有不少種方式,如jdk代理,cglib,ASM等框架
在說動態代理以前先說一下靜態代理ide
靜態代理在使用時,須要定義接口或者父類,被代理對象和代理對象一塊兒實現相同的接口或者繼承相同的父類this
靜態代理使用的是組合模式,在代理類中包含有被代理類的對象代理
public class TestStaticProxy { public static void main(String[] args) { NikeClothFactory nikeClothFactory = new NikeClothFactory(); ProxyFactory proxyFactory = new ProxyFactory(nikeClothFactory); proxyFactory.productCloth(); } } // 接口 interface ClothFactory{ void productCloth(); } // 被代理類 class NikeClothFactory implements ClothFactory{ @Override public void productCloth() { System.out.println("Nike工廠生產了一件Nike"); } } // 代理類 class ProxyFactory implements ClothFactory{ private ClothFactory clothFactory; public ProxyFactory(ClothFactory clothFactory){ this.clothFactory = clothFactory; } @Override public void productCloth() { System.out.println("代理類開始執行,準備調用被代理類"); clothFactory.productCloth(); } }
靜態代理雖然能夠在不修改目標對象功能的前提下對目標功能進行擴展,可是一旦接口增長方法,目標對象和代理類都要同時修改,並且代理對象和被代理對象要實現同樣的接口,致使有不少的代理類,不便於維護code
jdk動態代理的底層是用的是java的反射,可是jdk代理的前提是目標類必須實現接口xml
使用步驟對象
核心方法爲Proxy.newProxyInstance(ClassLoader,Class[],InvocationHandler)繼承
三個參數分別表示接口
public class TestDynamicProxy { public static void main(String[] args) { RealSubject realSubject = new RealSubject(); MyInvationHandler myInvationHandler = new MyInvationHandler(); Object obj = myInvationHandler.blind(realSubject); Subject sub = (Subject) obj; sub.action(); } } // 接口 interface Subject{ void action(); } // 真正執行的方法,被代理類 class RealSubject implements Subject{ @Override public void action() { System.out.println("被代理類開始執行"); } } class MyInvationHandler implements InvocationHandler{ // 實現了接口的被代理類的對象的聲明 Object obj; // 被代理類的實例 // 返回一個代理類的對象 public Object blind(Object obj){ this.obj = obj; // ①使用被代理類的類加載器②被代理類的接口③代理類的實例 return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),this); } /** * 當經過代理類的對象被重寫的方法調用時,都會轉換爲對invoke方法的調用 * @param proxy 正在返回的代理對象,通常狀況下,在invoke方法中不使用該對象 * @param method 正在被調用的方法 * @param args 調用方法時,傳入的參數 * @return * @throws Throwable */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { return method.invoke(obj,args); } }
靜態代理和jdk動態代理都妖氣目標對象必定要實現接口,可是有時候目標對象只是一個單獨的對象,並無實現任何接口,這個時候採用以目標對象子類的方式實現代理,該方法稱爲cglib代理
Cglib包的底層是經過使用一個字節碼處理框架ASM來轉換字節碼並生成新的類,因爲要生成子類,因此要被代理的類不能夠被final修飾
須要引入cglib的包
<dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>3.3.0</version> </dependency>
使用步驟
public class CglibProxy implements MethodInterceptor { public Object getProxy(Class clazz){ Enhancer enhancer = new Enhancer(); // 指定代理類的父類 enhancer.setSuperclass(clazz); // 設置Callback對象 enhancer.setCallback(this); // 經過字節碼技術動態建立子類實例 return enhancer.create(); } @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("前置處理"); // 調用MethodProxy.invokeSuper方法將調用轉發給原始對象 Object result = methodProxy.invokeSuper(o,objects); System.out.println("後置處理"); return result; } } public class Test { public void print(){ System.out.println("方法執行"); } public static void main(String[] args) { CglibProxy proxy = new CglibProxy(); Test proxyImp = (Test) proxy.getProxy(Test.class); proxyImp.print(); } }
因爲自己的博客百度沒有收錄,博客地址http://zhhll.icu