##什麼是代理? 經過代理控制對象的訪問,能夠詳細訪問某個對象的方法,在這個方法調用處理,或調用後處理。 ##代理應用場景 安全代理 能夠屏蔽真實角色 遠程代理 遠程調用代理類RMI 延遲加載 先加載輕量級代理類,真正須要在加載真實 ##代理的分類java
- 靜態代理(靜態定義代理類)
- 動態代理(動態生成代理類) 如 Jdk自帶動態代理, Cglib, javaassist(字節碼操做庫)
接下來舉個Sam賣房子的例子來看看三種代理模式: 靜態代理,jdk自帶動態代理,cglib動態代理。項目構建基於springboot。 ##靜態代理 賣房接口類spring
public interface House { //賣房 void sale(); }
Sam類實現賣房接口緩存
public class Sam implements House { @Override public void sale() { System.out.println("I'm Sam, I want sale my house !"); } }
靜態代理類,幫Sam賣房。安全
public class Proxy implements House { private Sam sam; public Proxy(Sam sam){ this.sam = sam; } @Override public void sale() { System.out.println("proxy listening sale start"); sam.sale(); System.out.println("proxy listening sale end"); } public static void main(String[] args) { Sam sam = new Sam(); Proxy proxy = new Proxy(sam); proxy.sale(); } }
經過反射機制來實現調用賣房方法。須要注意的是要實現InvocationHandler。springboot
/** * Jdk 動態代理 */ public class JDKProxy implements InvocationHandler { public Object target; public JDKProxy (Object target){ this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("我是房產中介,使用JDK動態代理監聽"); Object invoke = method.invoke(target, args); System.out.println("監聽完成!"); return invoke; } public static void main(String[] args) { Sam sam = new Sam(); JDKProxy jdkProxy = new JDKProxy(sam); House house = (House) Proxy.newProxyInstance(sam.getClass().getClassLoader(), sam.getClass().getInterfaces(), jdkProxy); house.sale(); } }
須要注意的是要實現MethodInterceptor接口。框架
public class CglibProxy implements MethodInterceptor { @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("cglib 代理開始監聽你了 "); Object object = methodProxy.invokeSuper(o, objects); System.out.println("cglib 代理監聽完成了! "); return object; } public static void main(String[] args) { CglibProxy cglibProxy = new CglibProxy(); //使用sam框架 Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(Sam.class); enhancer.setCallback(cglibProxy); //asm框架生成 House house = (House) enhancer.create(); house.sale(); } }
jdk動態代理是由Java內部的反射機制來實現的,cglib動態代理底層則是藉助asm來實現的。總的來講,反射機制在生成類的過程當中比較高效,而asm在生成類以後的相關執行過程當中比較高效(能夠經過將asm生成的類進行緩存,這樣解決asm生成類過程低效問題)。 還有一點必須注意:jdk動態代理的應用前提,必須是目標類基於統一的接口。若是沒有上述前提,jdk動態代理不能應用。ide
注:asm其實就是java字節碼控制.this