简介:动态代理是指在运行时,动态生成代理类。即代理类的字节码将在运行时生成并载入当前的ClassLoader。与静态代理类相比,有诸多好处。不需要为真实主题写一个形式上完全一样的封装类,若接口过多,则会代理接口也很多,接口稍微改动,代理接口也要进行变更;其次,使用动态代理可以在运行时指定代理类的执行逻辑,从而提升系统的灵活性。
动态代理有JDK自带的动态代理,CGLIB、Javassist或者ASM库。JDK的动态代理简单,内置在JDK中,因此不需要引入第三方jar包,但功能较弱。CGLIB和Javassist都是高级字节码生成库,总体性能比JDK自带的好,功能强大。这里主要介绍CGLIB的使用
1.在maven工程的pom.xml中引入cglib的配置
<dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>2.2.2</version> </dependency>
2.主题接口
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接口)
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,完成代理类和主题接口的工作
创建代理对象的步骤:
1) 指定切入器,定义代理类的逻辑
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代理模式的应用:一是属性的延迟加载;二是关联表的延迟加载。