深入剖析动态代理

JDK实现

1、步骤

3)通过反射机制获得动态代理类的构造函数,其唯一参数类型是调用处理器接口类型

4)通过构造函数创建动态代理类实例,构造时调用处理器对象作为参数被传入

2、创建代理

//InvocationHandlerImpl 实现了InvocationHandler接口,并能实现方法调用从代理类到委托类的分派转发//其内部通常包含指向委托类实例的引用,用于真正执行分派转发过来的方法调用InvocationHandler handler = new InvocaitonHandlerImpl(..);//通过Proxy为包括Interface接口在内的一组接口动态创建代理类的对象Class clazz = Proxy.getProxyClass(classLoader,new Class[]{Interface.class,…});//通过反射从生成的类对象获得构造函数对象Constructor constructor = clazz.getConstructor(new Class[]{InvocationHandler.class});//通过构造函数对象创建动态代理类实例Interface Proxy = (Interface)constructor.newInstance(new Object[]{handler});//Proxy类的静态方法newProxyInstance对上面具体步骤的后三步做了封装,,简化了动态代理对象的获取过程。//InvocationHandlerImpl实现了InvocaitonHandler接口,并能实现方法调用从代理类到委托类的分派转发InvocaitonHandler handler = new InvocationHandlerImpl(..);//通过Proxy直接创建动态代理类实例Interface proxy = (Interface)Proxy.newProxyInstance(classLoader,new Class[]{Interface.class},handler);

3、代码

/** * 接口 * @author Emily * */public interface IDBQuery {String request();}/** * 真实的实现类,具体的目标对象 * @author Emily * */public class DBQuery implements IDBQuery {public DBQuery(){try {Thread.sleep(1000); //可能包含数据库连接等耗时操作} catch (InterruptedException e) {e.printStackTrace();}}@Overridepublic String request() {return "request string";}}/** * JDK动态代理的实现类 * @author Emily * */public class JdkDbQueryHandler implements InvocationHandler{IDBQuery real = null; //主题接口/** * 生成Handler */@Overridepublic Object invoke(Object proxy, Method method, Object[] args)throws Throwable {if(real == null)real = new DBQuery(); //如果是第一次调用,则生成真实对象return real.request(); //使用真实主题完成实际的操作}/** * 利用Handler生成动态代理对象 * @return */public static IDBQuery createJdkProxy(){//根据指定的类加载器和接口以及截获器,返回代理类的一个实例对象//ClassLoader loader :指定被代理对象的类加载器//Class[] Interfaces :指定被代理对象所以事项的接口//InvocationHandler h :指定需要调用的InvocationHandler对象IDBQuery jdkProxy = (IDBQuery) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{IDBQuery.class}, new JdkDbQueryHandler());return jdkProxy;}}CGLIB实现package com.ltt.dynamic;import java.lang.reflect.Method;import net.sf.cglib.proxy.Enhancer;import net.sf.cglib.proxy.MethodInterceptor;import net.sf.cglib.proxy.MethodProxy;/** * CGLIB动态代理 * @author Emily * */public class CglibDbQueryInterceptor implements MethodInterceptor{IDBQuery real = null;/** * 处理代理逻辑的切入类 */@Overridepublic Object intercept(Object arg0, Method arg1, Object[] arg2,MethodProxy arg3) throws Throwable {if (real == null) { //代理类 的内部逻辑real = new DBQuery();return real.request();}return null;}/** * 生成动态代理 * @return */public static IDBQuery createCglibProxy(){Enhancer enhancer = new Enhancer();//指定切入器,定义代理类逻辑enhancer.setCallback(new CglibDbQueryInterceptor());//指定实现的接口enhancer.setInterfaces(new Class[]{IDBQuery.class});IDBQuery cglibProxy = (IDBQuery) enhancer.create();return cglibProxy;}}Javassist实现

一种是使用代理工厂创建,另一种通过使用动态代码创建。使用代理工厂创建时,方法与CGLIB类似,也需要实现一个用于代理逻辑处理的Handler:例如createJavassistDynProxy();使用动态代码创建,生成字节码,这种方式可以非常灵活,甚至可以在运行时生成业务逻辑,如createJavassistBytecodeDynamicProxy()方法。

/** * Javassist动态代理 * @author Emily * */public class JavassistDynDbQueryHandler implements MethodHandler{IDBQuery real = null;/* * (non-Javadoc) 实现用于代理逻辑处理的Handler * @see javassist.util.proxy.MethodHandler#invoke(java.lang.Object, java.lang.reflect.Method, java.lang.reflect.Method, java.lang.Object[]) */@Overridepublic Object invoke(Object arg0, Method arg1, Method arg2, Object[] arg3)throws Throwable {if (real == null)real = new DBQuery();return real.request();}/** * 创建动态代理 * @return * @throws Exception */public static IDBQuery createJavassistDynProxy() throws Exception{ProxyFactory proxyFactory = new ProxyFactory();proxyFactory.setInterfaces(new Class[]{IDBQuery.class}); //指定接口Class proxyClass = proxyFactory.createClass();IDBQuery javassistProxy = (IDBQuery) proxyClass.newInstance(); //设置Handler处理器((ProxyObject) javassistProxy).setHandler(new JavassistDynDbQueryHandler());return javassistProxy;}/** * 运行时生成业务逻辑 * @return * @throws Exception */public static IDBQuery createJavassistBytecodeDynamicProxy() throws Exception{ClassPool mPool = new ClassPool(true);//定义类名CtClass mCtc = mPool.makeClass(IDBQuery.class.getName() + "JavaassistBytecodeProxy");//需要实现接口mCtc.addInterface(mPool.get(IDBQuery.class.getName()));//添加构造函数mCtc.addConstructor(CtNewConstructor.defaultConstructor(mCtc));//添加类的字段信息,使用动态Java代码mCtc.addField(CtField.make("public" + IDBQuery.class.getName() + "real;", mCtc));String dbQueryname = DBQuery.class.getName();//添加方法,这里使用动态Java代码指定内部逻辑mCtc.addMethod(CtNewMethod.make("public String request() { if(real==null) real = new " +dbQueryname+"(); return real.request();}", mCtc));//基于以上信息,生成动态类Class pc = mCtc.toClass();//生成动态类的实例IDBQuery bytecodeProxy = (IDBQuery) pc.newInstance();return bytecodeProxy;}} 三种动态代理:

动态代理 VS 静态代理

静态代理

动态代理

如果心在远方,只需勇敢前行,梦想自会引路,

深入剖析动态代理

相关文章:

你感兴趣的文章:

标签云: