java动态代理源码解析
2021-06-22 02:03
标签:record rgs oid play fun tst via lis div 众所周知,java动态代理同反射原理一直是许多框架的底层实现,之前一直没有时间来分析动态代理的底层源码,现结合源码分析一下动态代理的底层实现 java动态代理的主要类和接口有:java.lang.reflect.Proxy、java.lang.reflect.InvocationHandler 1、public static InvocationHandler getInvocationHandler(Object var0) -> 该方法用于获取指定代理对象所关联的调用处理器 2、public static Class> getProxyClass(ClassLoader var0, Class... var1) -> 该方法用于获取关联于指定类装载器和一组接口的动态代理类的类对象 3、public static Object newProxyInstance(ClassLoader var0, Class>[] var1, InvocationHandler var2) ->方法用于为指定类装载器、一组接口及调用处理器生成动态代理类实例 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable; 将类的字节码装载到 Java 虚拟机(JVM)中并为其定义类对象,然后该类才能被使用。Proxy类与普通类的唯一区别就是其字节码是由 JVM 在运行时动态生成的而非预存在于任何一个 .class 文件中。 从newProxyInstance方法看出,产生代理类核心代码在getProxyClass0 getProxyClass0通过类加载器和接口集合去缓存里面获取,如果能找到代理类就直接返回,否则就会调用ProxyClassFactory这个工厂去生成一个代理类,下面我们看下Proxy的静态内部类ProxyClassFactory ProxyClassFactory中生成代理类核心代码 byte[] proxyClassFile = ProxyGenerator.generateProxyClass(proxyName, interfaces, accessFlags);下面我们继续分析ProxyGenerator.generateProxyClass 跟踪了这么久源码,大boss终于出现了,下面我们分析ProxyGenerator.generateClassFile方法 动态代理的本质:通过类加载器获取类字节码,通过类实现的接口反射获得该类的属性,方法等,并生成新的字节码文件 代理类$Proxy0调用了invocationHandler也就是的helloServiceProxy的invoke方法,而invoke通过反射执行了HelloService 的sayHello方法也就是HelloServiceImpl的sayHello方法。 自此java动态代理源码分析完成,笔者对动态代理理解更加深刻,如有不当之处还请各位读者指正 java动态代理源码解析 标签:record rgs oid play fun tst via lis div 原文地址:https://www.cnblogs.com/allenli263/p/9621750.html类和接口
1 java.lang.reflect.Proxy:动态代理机制的主类,提供一组静态方法为一组接口动态的生成对象和代理类。
2 java.lang.reflect.InvocationHandler:调用处理器接口,自定义invoke方法,用于实现对于真正委托类的代理访问
3 java.lang.ClassLoader:类装载器类
demo
public interface HelloService {
void sayHello();
}
public class HelloServiceImpl implements HelloService{
@Override
public void sayHello() {
System.out.println("hello 张三");
}
}
public class HelloServiceProxy implements InvocationHandler{
private Object target;
public Object bind(Object target, Class[] interfaces) {
this.target = target;
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result;
System.out.println("###########这里是动态代理##########");
//反射方法前调用
System.out.println("调用前");
//反射执行方法 相当于调用target.sayHelllo;
result = method.invoke(target,args);
//反射方法后调用.
System.out.println("调用后");
return result;
}
}
public class ProxyTest {
public static void main(String[] args) {
HelloServiceProxy proxy = new HelloServiceProxy();
HelloService service = new HelloServiceImpl();
HelloService serviceProxy = (HelloService)proxy.bind(service, new Class[] {HelloService.class});
serviceProxy.sayHello();
}
}
运行结果:
源码分析:
1 Proxy类的静态方法newProxyInstance方法
public static Object newProxyInstance(ClassLoader loader,
Class>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
//验证传入的InvocationHandler是否为空
Objects.requireNonNull(h);
//克隆代理类实现的接口
final Class>[] intfs = interfaces.clone();
//获得安全管理器
final SecurityManager sm = System.getSecurityManager();
//检查创建代理类所需的权限
if (sm != null) {
checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
}
/*
* Look up or generate the designated proxy class.
* 查找或者生成特定的代理类(如果缓存中存在,则直接获取)
*/
Class> cl = getProxyClass0(loader, intfs);
/*
* Invoke its constructor with the designated invocation handler.
*/
try {
//权限校验
if (sm != null) {
checkNewProxyPermission(Reflection.getCallerClass(), cl);
}
//获取参数类型是InvocationHandler.class的代理类构造器
final Constructor> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h;
//如果代理类是不可访问的, 就使用特权将它的构造器设置为可访问
if (!Modifier.isPublic(cl.getModifiers())) {
AccessController.doPrivileged(new PrivilegedAction
2 Proxy类的静态方法getProxyClass0方法
1 private static Class> getProxyClass0(ClassLoader loader,
2 Class>... interfaces) {
3 if (interfaces.length > 65535) {
4 throw new IllegalArgumentException("interface limit exceeded");
5 }
6
7 // If the proxy class defined by the given loader implementing
8 // the given interfaces exists, this will simply return the cached copy;
9 // otherwise, it will create the proxy class via the ProxyClassFactory
10 //如果由实现给定接口的代理类存在,这将简单地返回缓存的副本;否则,将通过ProxyClassFactory创建代理类
11 return proxyClassCache.get(loader, interfaces);
12 }
3 ProxyClassFactory
1 private static final class ProxyClassFactory
2 implements BiFunction
4 ProxyGenerator.generateProxyClass
1 public static byte[] generateProxyClass(final String var0, Class>[] var1, int var2) {
2 //构造ProxyGenerator对象
3 ProxyGenerator var3 = new ProxyGenerator(var0, var1, var2);
4 //核心代码,生成代理类字节码文件
5 final byte[] var4 = var3.generateClassFile();
6 //如果需要保存生成的字节码文件,则将字节码文件写入磁盘
7 if(saveGeneratedFiles) {
8 AccessController.doPrivileged(new PrivilegedAction() {
9 public Void run() {
10 try {
11 int var1 = var0.lastIndexOf(46);
12 Path var2;
13 //生成存储路径
14 if(var1 > 0) {
15 Path var3 = Paths.get(var0.substring(0, var1).replace(‘.‘, File.separatorChar), new String[0]);
16 Files.createDirectories(var3, new FileAttribute[0]);
17 var2 = var3.resolve(var0.substring(var1 + 1, var0.length()) + ".class");
18 } else {
19 var2 = Paths.get(var0 + ".class", new String[0]);
20 }
21 //将字节码文件写入磁盘
22 Files.write(var2, var4, new OpenOption[0]);
23 return null;
24 } catch (IOException var4x) {
25 throw new InternalError("I/O exception saving generated file: " + var4x);
26 }
27 }
28 });
29 }
30 //返回字节码文件
31 return var4;
32 }
5 ProxyGenerator.generateClassFile
1 private byte[] generateClassFile() {
2 //1、将所有的方法组装成ProxyMethod对象
3 //首先为代理类生成toString, hashCode, equals等代理方法
4 this.addProxyMethod(hashCodeMethod, Object.class);
5 this.addProxyMethod(equalsMethod, Object.class);
6 this.addProxyMethod(toStringMethod, Object.class);
7 Class[] var1 = this.interfaces;
8 int var2 = var1.length;
9
10 int var3;
11 Class var4;
12 //遍历每一个接口的每一个方法, 并生成ProxyMethod对象
13 for(var3 = 0; var3 var3) {
14 var4 = var1[var3];
15 Method[] var5 = var4.getMethods();
16 int var6 = var5.length;
17
18 for(int var7 = 0; var7 var7) {
19 Method var8 = var5[var7];
20 this.addProxyMethod(var8, var4);
21 }
22 }
23
24 Iterator var11 = this.proxyMethods.values().iterator();
25
26 List var12;
27 while(var11.hasNext()) {
28 var12 = (List)var11.next();
29 checkReturnTypes(var12);
30 }
31
32 //2、组装要生成的class文件的所有的字段信息和方法信息
33 Iterator var15;
34 try {
35 //添加构造器方法
36 this.methods.add(this.generateConstructor());
37 var11 = this.proxyMethods.values().iterator();
38
39 //遍历缓存中的代理方法
40 while(var11.hasNext()) {
41 var12 = (List)var11.next();
42 var15 = var12.iterator();
43
44 while(var15.hasNext()) {
45 ProxyGenerator.ProxyMethod var16 = (ProxyGenerator.ProxyMethod)var15.next();
46 //添加代理类的静态字段, 例如:private static Method m1;
47 this.fields.add(new ProxyGenerator.FieldInfo(var16.methodFieldName, "Ljava/lang/reflect/Method;", 10));
48 //添加代理类的代理方法
49 this.methods.add(var16.generateMethod());
50 }
51 }
52
53 //添加代理类的静态字段初始化方法
54 this.methods.add(this.generateStaticInitializer());
55 } catch (IOException var10) {
56 throw new InternalError("unexpected I/O Exception", var10);
57 }
58
59 if(this.methods.size() > ‘\uffff‘) {
60 throw new IllegalArgumentException("method limit exceeded");
61 } else if(this.fields.size() > ‘\uffff‘) {
62 throw new IllegalArgumentException("field limit exceeded");
63 } else {
64 //3、写入最终的class文件
65 //验证常量池中存在代理类的全限定名
66 this.cp.getClass(dotToSlash(this.className));
67 //验证常量池中存在代理类父类的全限定名
68 this.cp.getClass("java/lang/reflect/Proxy");
69 var1 = this.interfaces;
70 var2 = var1.length;
71
72 //验证常量池存在代理类接口的全限定名
73 for(var3 = 0; var3 var3) {
74 var4 = var1[var3];
75 this.cp.getClass(dotToSlash(var4.getName()));
76 }
77
78 //接下来要开始写入文件了,设置常量池只读
79 this.cp.setReadOnly();
80 ByteArrayOutputStream var13 = new ByteArrayOutputStream();
81 DataOutputStream var14 = new DataOutputStream(var13);
82
83 try {
84 //1.写入魔数
85 var14.writeInt(-889275714);
86 //2.写入次版本号
87 var14.writeShort(0);
88 //3.写入主版本号
89 var14.writeShort(49);
90 //4.写入常量池
91 this.cp.write(var14);
92 //5.写入访问修饰符
93 var14.writeShort(this.accessFlags);
94 //6.写入类索引
95 var14.writeShort(this.cp.getClass(dotToSlash(this.className)));
96 //7.写入父类索引, 生成的代理类都继承自Proxy
97 var14.writeShort(this.cp.getClass("java/lang/reflect/Proxy"));
98 //8.写入接口计数值
99 var14.writeShort(this.interfaces.length);
100
101 Class[] var17 = this.interfaces;
102 int var18 = var17.length;
103
104 //9.写入接口集合
105 for(int var19 = 0; var19 var19) {
106 Class var22 = var17[var19];
107 var14.writeShort(this.cp.getClass(dotToSlash(var22.getName())));
108 }
109 //10.写入字段计数值
110 var14.writeShort(this.fields.size());
111 var15 = this.fields.iterator();
112 //11.写入字段集合
113 while(var15.hasNext()) {
114 ProxyGenerator.FieldInfo var20 = (ProxyGenerator.FieldInfo)var15.next();
115 var20.write(var14);
116 }
117 //12.写入方法计数值
118 var14.writeShort(this.methods.size());
119 var15 = this.methods.iterator();
120 //13.写入方法集合
121 while(var15.hasNext()) {
122 ProxyGenerator.MethodInfo var21 = (ProxyGenerator.MethodInfo)var15.next();
123 var21.write(var14);
124 }
125 //14.写入属性计数值, 代理类class文件没有属性所以为0
126 var14.writeShort(0);
127 //转换成二进制数组输出
128 return var13.toByteArray();
129 } catch (IOException var9) {
130 throw new InternalError("unexpected I/O Exception", var9);
131 }
132 }
133 }
6 代理类字节码文件分析 $Proxy0.class
1 package com.sun.proxy;
2
3 import com.doubibi.framework.util.proxy.HelloService;
4 import java.lang.reflect.InvocationHandler;
5 import java.lang.reflect.Method;
6 import java.lang.reflect.Proxy;
7 import java.lang.reflect.UndeclaredThrowableException;
8
9 public final class $Proxy0 extends Proxy
10 implements HelloService
11 {
12 //equals方法
13 private static Method m1;
14 //HelloService 的sayHello方法
15 private static Method m3;
16 //toString方法
17 private static Method m2;
18 //hashCode方法
19 private static Method m0;
20
21 //构造方法
22 public $Proxy0(InvocationHandler paramInvocationHandler)
23 throws
24 {
25 super(paramInvocationHandler);
26 }
27
28 public final boolean equals(Object paramObject)
29 throws
30 {
31 try
32 {
33 return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue();
34 }
35 catch (Error|RuntimeException localError)
36 {
37 throw localError;
38 }
39 catch (Throwable localThrowable)
40 {
41 throw new UndeclaredThrowableException(localThrowable);
42 }
43 }
44
45 //调用了invocationHandler的invoke方法,invoke执行了HelloService 的sayHello方法
46 public final void sayHello()
47 throws
48 {
49 try
50 {
51 this.h.invoke(this, m3, null);
52 return;
53 }
54 catch (Error|RuntimeException localError)
55 {
56 throw localError;
57 }
58 catch (Throwable localThrowable)
59 {
60 throw new UndeclaredThrowableException(localThrowable);
61 }
62 }
63
64 public final String toString()
65 throws
66 {
67 try
68 {
69 return (String)this.h.invoke(this, m2, null);
70 }
71 catch (Error|RuntimeException localError)
72 {
73 throw localError;
74 }
75 catch (Throwable localThrowable)
76 {
77 throw new UndeclaredThrowableException(localThrowable);
78 }
79 }
80
81 public final int hashCode()
82 throws
83 {
84 try
85 {
86 return ((Integer)this.h.invoke(this, m0, null)).intValue();
87 }
88 catch (Error|RuntimeException localError)
89 {
90 throw localError;
91 }
92 catch (Throwable localThrowable)
93 {
94 throw new UndeclaredThrowableException(localThrowable);
95 }
96 }
97
98 static
99 {
100 try
101 {
102 m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });
103 m3 = Class.forName("com.doubibi.framework.util.proxy.HelloService").getMethod("sayHello", new Class[0]);
104 m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
105 m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
106 return;
107 }
108 catch (NoSuchMethodException localNoSuchMethodException)
109 {
110 throw new NoSuchMethodError(localNoSuchMethodException.getMessage());
111 }
112 catch (ClassNotFoundException localClassNotFoundException)
113 {
114 throw new NoClassDefFoundError(localClassNotFoundException.getMessage());
115 }
116 }
117 }