簡介:動態代理是指在運行時,動態生成代理類。即代理類的字節碼將在運行時生成並載入當前的ClassLoader。與靜態代理類相比,有諸多好處。不須要爲真實主題寫一個形式上徹底同樣的封裝類,若接口過多,則會代理接口也不少,接口稍微改動,代理接口也要進行變動;其次,使用動態代理能夠在運行時指定代理類的執行邏輯,從而提高系統的靈活性。java
動態代理有JDK自帶的動態代理,CGLIB、Javassist或者ASM庫。JDK的動態代理簡單,內置在JDK中,所以不須要引入第三方jar包,但功能較弱。CGLIB和Javassist都是高級字節碼生成庫,整體性能比JDK自帶的好,功能強大。這裏主要介紹CGLIB的使用maven
1.在maven工程的pom.xml中引入cglib的配置性能
<dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>2.2.2</version> </dependency>
2.主題接口spa
package com.hxc.proxy.proxyMode; /** * <p>Description: 主題接口</p> * @author Huang Xiaocong * @data 2019年10月27日 */ public interface IDBQuery { String request(); }
3.真實主題代理
package com.hxc.proxy.proxyMode; /** * <p>Description: 真實主題</p> * @author Huang Xiaocong * @data 2019年10月27日 */ public class DBQuery implements IDBQuery { public DBQuery() { try { Thread.sleep(1000); //模擬執行過程 } catch (InterruptedException e) { e.printStackTrace(); } } public String request() { return "request String"; } }
4.代理類 CGLIB代理類實現MethodInterceptor接口(JDK自帶的動態代理實現InvocationHandler接口)code
package com.hxc.proxy.proxyMode; import java.lang.reflect.Method; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; /** * <p>Description: 代理類</p> * @author Huang Xiaocong * @data 2019年10月30日 */ public class CglibDbQueryInterceptor implements MethodInterceptor { private IDBQuery real = null; public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { if(real == null) { real = new DBQuery(); } return real; } }
5.Main,完成代理類和主題接口的工做xml
建立代理對象的步驟:對象
1) 指定切入器,定義代理類的邏輯blog
2)指定實現的接口接口
3)生成代理類的實例
package com.hxc.proxy.proxyMode; import net.sf.cglib.proxy.Enhancer; /** * <p>Description: 客戶端</p> * @author Huang Xiaocong * @data 2019年10月27日 */ public class Main { public static void main(String[] args) { IDBQuery dbQuery = createCglibProxy(); String request = dbQuery.request(); System.out.println(request); } public static IDBQuery createCglibProxy() { Enhancer enhance = new Enhancer(); enhance.setCallback(new CglibDbQueryInterceptor()); //指定切入器,定義代理類邏輯 //指定實現的接口 enhance.setInterfaces(new Class[] {IDBQuery.class}); //生成代理類的實例 IDBQuery object = (IDBQuery) enhance.create(); return object; } }
對動態代理最經典的用例就是Hibernate代理模式的應用:一是屬性的延遲加載;二是關聯表的延遲加載。