Java 設計模式之代理模式,Java 靜態代理,Java 動態代理
Java 設計模式之代理模式,Java 靜態代理,Java 動態代理
================================
©Copyright 蕃薯耀2021-06-21
https://www.cnblogs.com/fanshuyao/
一、Java 靜態代理
1、定義介面
public interface IHouse { //賣房子 void sale(); //檢視房子資訊 String house(); }
2、被代理的物件類(實際操作類)
public class HouseOwner implements IHouse { @Overridepublic void sale() { System.out.println("。。。我將房子賣了"); } @Override public String house() { return "該房子在深圳福田,售價:1.2億"; } }
3、代理類
public class HouseProxy implements IHouse { //被代理的物件 private HouseOwner houseOwner; public HouseProxy(HouseOwner houseOwner) {this.houseOwner = houseOwner; } @Override public void sale() { System.out.println("【中介】在賣房前做了什麼"); houseOwner.sale(); System.out.println("【中介】在賣後收了多少佣金"); } @Override public String house() { return houseOwner.house(); } }
4、測試
public classProxyStatic { public static void main(String[] args) { HouseProxy houseProxy = new HouseProxy(new HouseOwner()); houseProxy.sale(); System.out.println("=============================="); System.out.println(houseProxy.house()); } }
結果:
【中介】在賣房前做了什麼 。。。我將房子賣了 【中介】在賣後收了多少佣金 ============================== 該房子在深圳福田,售價:1.2億
二、JavaJdk動態代理
1、動態代理類
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class DynamicProxyFactoryJdk{ private Object proxyTarget; public DynamicProxyFactoryJdk(Object proxyTarget) { this.proxyTarget = proxyTarget; } public Object getProxyInstance() { return Proxy.newProxyInstance(proxyTarget.getClass().getClassLoader(), proxyTarget.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("jdk動態代理開始…"); System.out.println("method.getName()="+ method.getName()); Object returnObject = method.invoke(proxyTarget, args);//此處是proxyTarget物件,不是proxy引數 System.out.println("jdk動態代理結束。"); return returnObject; } }); } }
2、測試
public class ProxyDynamicJdk { public static void main(String[] args) { IHouse proxyTarget = new HouseOwner(); IHouse houseProxy = (IHouse) new DynamicProxyFactoryJdk(proxyTarget).getProxyInstance(); System.out.println("+++++++++++++++++++++++++++++++"); System.out.println("houseProxy=" + houseProxy); System.out.println("houseProxy.getClass().getName()=" + houseProxy.getClass().getName()); System.out.println("=============================="); houseProxy.sale(); System.out.println("=============================="); System.out.println(houseProxy.house()); } }
結果:
+++++++++++++++++++++++++++++++ jdk動態代理開始… method.getName()=toString jdk動態代理結束。 houseProxy=com.lqy.springCloud.zzjava.designPattern.proxy.HouseOwner@6bc7c054 houseProxy.getClass().getName()=com.sun.proxy.$Proxy0 ============================== jdk動態代理開始… method.getName()=sale 。。。我將房子賣了 jdk動態代理結束。 ============================== jdk動態代理開始… method.getName()=house jdk動態代理結束。 該房子在深圳福田,售價:1.2億
三、Java cglib 動態代理
1、動態代理類(需要需要引入cglib相關包)
<dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>3.3.0</version> </dependency>
import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; /** * 需要引入cglib包 * */ public class DynamicProxyFactoryCglib implements MethodInterceptor{ private Object proxyTarget; public DynamicProxyFactoryCglib(Object proxyTarget) { this.proxyTarget = proxyTarget; } public Object getProxyInstance() { return Enhancer.create(proxyTarget.getClass(), this); } @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println("cglib動態代理開始…"); System.out.println("method.getName()="+ method.getName()); Object returnObject = method.invoke(proxyTarget, args);//此處是proxyTarget物件,不是obj引數 System.out.println("cglib動態代理結束。"); return returnObject; } }
2、測試
public class ProxyDynamicCglib { public static void main(String[] args) { HouseOwner houseOwner = (HouseOwner) new DynamicProxyFactoryCglib(new HouseOwner()).getProxyInstance(); System.out.println("+++++++++++++++++++++++++++++++"); System.out.println("houseOwner=" + houseOwner); System.out.println("houseOwner.getClass().getName()=" + houseOwner.getClass().getName()); System.out.println("=============================="); houseOwner.sale(); System.out.println("=============================="); System.out.println(houseOwner.house()); } }
結果:
+++++++++++++++++++++++++++++++ cglib動態代理開始… method.getName()=toString cglib動態代理結束。 houseOwner=com.lqy.springCloud.zzjava.designPattern.proxy.HouseOwner@6842775d houseOwner.getClass().getName()=com.lqy.springCloud.zzjava.designPattern.proxy.HouseOwner$$EnhancerByCGLIB$$8067e885 ============================== cglib動態代理開始… method.getName()=sale 。。。我將房子賣了 cglib動態代理結束。 ============================== cglib動態代理開始… method.getName()=house cglib動態代理結束。 該房子在深圳福田,售價:1.2億
四、總結
靜態代理:
實現較簡單,只要宣告一個代理物件對目標物件進行包裝,即可實現代理功能,但靜態代理只能為一個目標物件服務,如果目標物件過多,則會產生很多代理類。
靜態代理在編譯時產生class位元組碼檔案,可以直接使用,效率高。
JDK 動態代理:
需要目標物件實現業務介面(目標類和代理類必須實現相同的介面),代理類只需實現InvocationHandler介面。
動態代理必須實現InvocationHandler介面,通過反射代理方法,比較消耗系統性能,但可以減少代理類的數量,使用更靈活。
cglib 動態代理:
cglib (Code Generation Library )是一個第三方程式碼生成類庫,執行時在記憶體中動態生成一個子類物件從而實現對目標物件功能的擴充套件。
使用cglib需要引入cglib的jar包
cglib代理無需實現介面,通過生成類位元組碼實現代理,比反射稍快,不存在效能問題,但cglib會繼承目標物件,需要重寫方法,所以目標物件不能為final類。
使用cglib代理的物件則無需實現介面,達到代理類無侵入。
================================
©Copyright 蕃薯耀2021-06-21
https://www.cnblogs.com/fanshuyao/