在前文Java反射(三)反射与代理设计模式 中描述了动态代理的使用方法,本文主要记录Java动态代理的实现原理。
大致思路:(1)用户通过Proxy.newProxyInstance方法,传入ClassLoader、接口数组、和InvocationHandler实现类(包含具体被代理对象和对其具体处理逻辑);
(2)底层根据接口数组和InvocationHandler在运行时生成代理类字节码,即代理类实现接口数组,同时组合InvocationHandler,对被代理类添加额外功能;
(3)然后通过传入的ClassLoader进行加载,再实例化后返回,即得到代理对象。
1.代理核心类
(1) ProxyClassFactory类
代理类创建工厂类ProxyClassFactory,作为Proxy嵌套类,根据ClassLoader和接口数组定义代理Class,核心代码如下:
/** * 代理Class工厂,可以根据ClassLoader和接口数组定义代理Class(A factory function that generates, defines and returns the proxy class given * the ClassLoader and array of interfaces.) */ private static final class ProxyClassFactory implements BiFunction<ClassLoader, Class<?>[], Class<?>> { // 代理类的前缀(prefix for all proxy class names) private static final String proxyClassNamePrefix = "$Proxy"; // 为下一个代理类生成唯一序号(next number to use for generation of unique proxy class names) private static final AtomicLong nextUniqueNumber = new AtomicLong(); //具体生成代理class方法 @Override public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) { //接口校验等处理 //方法访问修饰符,public和final int accessFlags = Modifier.PUBLIC | Modifier.FINAL; //构建代理类名称 String proxyName = proxyPkg + proxyClassNamePrefix + num; //生成代理类字节码(Generate the specified proxy class.) byte[] proxyClassFile = ProxyGenerator.generateProxyClass( proxyName, interfaces, accessFlags); try { //根据传入的ClassLoader加载代理类 return defineClass0(loader, proxyName, proxyClassFile, 0, proxyClassFile.length); } catch (ClassFormatError e) { } } }
其中 byte[] proxyClassFile = ProxyGenerator.generateProxyClass(proxyName, interfaces, accessFlags);,通过ProxyGenerator类生成的字节数组即为代理类字节码,然后通过传入的ClassLoader进行加载。
(2)Proxy类
静态方法newProxyInstance,是代理类实现的入口,开发者传入ClassLoader、被代理的接口和自定义的InvocationHandler。
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException { //(1)查找或生成代理类 Class<?> cl = getProxyClass0(loader, intfs); //调用代理类构造器,并注入invocation handler. try { //获取代理类的构造函数,如果是非Public,修改访问权限 final Constructor<?> cons = cl.getConstructor(constructorParams); final InvocationHandler ih = h; if (!Modifier.isPublic(cl.getModifiers())) { AccessController.doPrivileged(new PrivilegedAction<Void>() { public Void run() { cons.setAccessible(true); return null; } }); } //(2)实例化代理类,将InvocationHandler作为参数注入代理类 return cons.newInstance(new Object[]{h}); } catch (IllegalAccessException|InstantiationException e) { } catch (InvocationTargetException e) { } catch (NoSuchMethodException e) { } }
(1)getProxyClass0方法是查找或生成代理类的方法,它是在缓存中查找是否存在代理类,如果不存在则通过调代理工厂类生成。
/** * a cache of proxy classes */ private static final WeakCache<ClassLoader, Class<?>[], Class<?>> proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory()); private static Class<?> getProxyClass0(ClassLoader loader, Class<?>... interfaces) { //接口数量不能大于65535 if (interfaces.length > 65535) { throw new IllegalArgumentException("interface limit exceeded"); } //如果缓存中存在,则直接返回;否则通过ProxyClassFactory工厂创建 return proxyClassCache.get(loader, interfaces); }
(2)cons.newInstance(new Object[]{h}),创建代理类实例,将InvocationHandler注入代理类中。Proxy类通过组合方式包含InvocationHandler类,代理类在实现传入接口的同时,还会继承Proxy(后文可见)。
/** * the invocation handler for this proxy instance. * @serial */ protected InvocationHandler h; /** * Constructs a new {@code Proxy} instance from a subclass * (typically, a dynamic proxy class) with the specified value * for its invocation handler. * * @param h the invocation handler for this proxy instance * * @throws NullPointerException if the given invocation handler, {@code h}, * is {@code null}. */ protected Proxy(InvocationHandler h) { Objects.requireNonNull(h); this.h = h; }
2.代理类结构
(1)定义被代理的接口和实现类,存在2个方法
interface Msg{ void send(String msg, int seq); String recv(String msg); } class MsgImpl implements Msg{ public void send(String msg,int seq) { System.out.println("消息发送:"+msg); System.out.println("消息序号:"+seq); } public String recv(String msg) { System.out.println("消息接收:"+msg); return msg; } }
(2)将ProxyClassFactory工厂类中关键代码抽出,获取代理类字节码
public class ReflectFile { public static void main(String[]args) throws Exception{ //方法修饰符 public和final int accessFlags = Modifier.PUBLIC | Modifier.FINAL; //代理类名称 String proxyName = "MsgImplProxy"; //ProxyGenerator类生成代理类字节码 byte[] proxyClassFile = ProxyGenerator.generateProxyClass( proxyName, MsgImpl.class.getInterfaces(), accessFlags); //输出到class文件中 FileOutputStream out = new FileOutputStream(new File(proxyName+".class")); out.write(proxyClassFile); out.close(); } }
(3)反编译代理类,详细信息见注解
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.lang.reflect.UndeclaredThrowableException; import test.Msg; /** *代理类MsgImplProxy继承自Proxy(包含InvocationHandler,处理代理逻辑),并实现Msg(代理三要素中的接口) */ public final class MsgImplProxy extends Proxy implements Msg { //包含5个方法,其中m0、m1、m2为Object方法hashCode、equals、toString;m3 和 m4是被代理接口的方法 //方法初始化放在static中,在类加载时进行初始化 private static Method m1; private static Method m2; private static Method m4; private static Method m3; private static Method m0; static { try { m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[]{Class.forName("java.lang.Object")}); m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]); m4 = Class.forName("test.Msg").getMethod("send", new Class[]{Class.forName("java.lang.String"), Integer.TYPE}); m3 = Class.forName("test.Msg").getMethod("recv", new Class[]{Class.forName("java.lang.String")}); m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]); } catch (NoSuchMethodException var2) { throw new NoSuchMethodError(var2.getMessage()); } catch (ClassNotFoundException var3) { throw new NoClassDefFoundError(var3.getMessage()); } } //代理类构造函数,参数为InvocationHandler,调用父类Proxy的构造,将InvocationHandler设置到变量中 public MsgImplProxy(InvocationHandler var1) throws { super(var1); } public final boolean equals(Object var1) throws { try { return ((Boolean)super.h.invoke(this, m1, new Object[]{var1})).booleanValue(); } catch (RuntimeException | Error var3) { throw var3; } catch (Throwable var4) { throw new UndeclaredThrowableException(var4); } } public final String toString() throws { try { return (String)super.h.invoke(this, m2, (Object[])null); } catch (RuntimeException | Error var2) { throw var2; } catch (Throwable var3) { throw new UndeclaredThrowableException(var3); } } //被代理接口方法send public final void send(String var1, int var2) throws { try { //调用InvocationHandler的invoke方法,传入代理对象、被代理方法实例、被代理方法参数 super.h.invoke(this, m4, new Object[]{var1, Integer.valueOf(var2)}); } catch (RuntimeException | Error var4) { throw var4; } catch (Throwable var5) { throw new UndeclaredThrowableException(var5); } } //被代理接口方法recv public final String recv(String var1) throws { try { return (String)super.h.invoke(this, m3, new Object[]{var1}); } catch (RuntimeException | Error var3) { throw var3; } catch (Throwable var4) { throw new UndeclaredThrowableException(var4); } } public final int hashCode() throws { try { return ((Integer)super.h.invoke(this, m0, (Object[])null)).intValue(); } catch (RuntimeException | Error var2) { throw var2; } catch (Throwable var3) { throw new UndeclaredThrowableException(var3); } } }
综上:
(1)Proxy创建的代理类MsgImplProxy继承Proxy,同时还实现被代理类接口,与静态代理相似 。
(2)代理类执行方法调用时,会调InvocationHandler的invoke方法,该方法是开发者自定义功能的地方。
(3)在构造InvocationHandler时,需要将被代理类对象传入(因为需要执行 method.invoke(被代理对象,方法参数)),从而实现被代理对象的代理和附加额外的功能。
(4)下篇文章将采用注解、反射、动态代理、工厂模式进行实践。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/16212.html