动态代理的意义在于生成一个占位(又称代理对象),来代理真实的对象,从而控制真实对象的访问
、
JDK动态代理
定义接口
1 2 3 | public interface HelloWorld { public void sayHelloWorld(); } |
接口实现类
1 2 3 4 5 6 7 8 | public class HelloWorldImpl implements HelloWorld { @Override public void sayHelloWorld() { System.out.println("Hello World"); } } |
在JDK动态代理中,要实现代理逻辑类必须实现java.lang.reflect.InvocationHandler接口,它里面定义了一个invoke方法,并提供接口数组用于下挂代理对象
源码如下
1 2 3 4 | public interface InvocationHandler { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable; } |
实现如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class JdkProxyExample implements InvocationHandler { // 真实对象 private Object target = null; /** * 建立代理对象和真实对象的代理关系,并返回代理对象 * * @param target真实对象 * @return 代理对象 */ public Object bind(Object target) { this.target = target; return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this); } /** * 代理方法逻辑 * * @param proxy * --代理对象 * @param method * --当前调度方法 * @param args * --当前方法参数 * @return 代理结果返回 * @throws Throwable * 异常 */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("进入代理逻辑方法"); System.out.println("在调度真实对象之前的服务"); Object obj = method.invoke(target, args);// 相当于调用sayHelloWorld方法 System.out.println("在调度真实对象之后的服务"); return obj; } } |
测试Demo
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | public class ProxyTest { public static void main(String[] args) { testJdkProxy(); // tesCGLIBProxy(); } public static void testJdkProxy() { JdkProxyExample jdk = new JdkProxyExample(); HelloWorld proxy = (HelloWorld) jdk.bind(new HelloWorldImpl()); proxy.sayHelloWorld(); } // public static void tesCGLIBProxy() { // CglibProxyExample cpe = new CglibProxyExample(); // ReflectServiceImpl obj = (ReflectServiceImpl)cpe.getProxy(ReflectServiceImpl.class); // obj.sayHello("zhangsan"); // } } |
运行结果
可以查看生成的代理类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | import sun.misc.ProxyGenerator; import java.io.File; import java.io.FileOutputStream; public class ProxyTest { public static void main(String[] args) throws Exception { testJdkProxy(); // tesCGLIBProxy(); } public static void testJdkProxy() { System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true"); try{ JdkProxyExample jdk = new JdkProxyExample(); HelloWorld proxy = (HelloWorld) jdk.bind(new HelloWorldImpl()); proxy.sayHelloWorld(); Class<?>[] interfaces=proxy.getClass().getInterfaces(); byte[] bts=ProxyGenerator.generateProxyClass("$HelloWorldProxy",interfaces); FileOutputStream fos=new FileOutputStream(new File("$HelloWorldProxy.class")); fos.write(bts); fos.flush(); fos.close(); }catch(Exception e){ e.printStackTrace(); } } } |
生成的代理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.lang.reflect.UndeclaredThrowableException; public final class $HelloWorldProxy extends Proxy implements HelloWorld { private static Method m1; private static Method m2; private static Method m3; private static Method m0; public $HelloWorldProxy(InvocationHandler var1) throws { super(var1); } public final boolean equals(Object var1) throws { try { return (Boolean)super.h.invoke(this, m1, new Object[]{var1}); } 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); } } public final void sayHelloWorld() throws { try { super.h.invoke(this, m3, (Object[])null); } catch (RuntimeException | Error var2) { throw var2; } catch (Throwable var3) { throw new UndeclaredThrowableException(var3); } } public final int hashCode() throws { try { return (Integer)super.h.invoke(this, m0, (Object[])null); } catch (RuntimeException | Error var2) { throw var2; } catch (Throwable var3) { throw new UndeclaredThrowableException(var3); } } static { try { m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object")); m2 = Class.forName("java.lang.Object").getMethod("toString"); m3 = Class.forName("HelloWorld").getMethod("sayHelloWorld"); m0 = Class.forName("java.lang.Object").getMethod("hashCode"); } catch (NoSuchMethodException var2) { throw new NoSuchMethodError(var2.getMessage()); } catch (ClassNotFoundException var3) { throw new NoClassDefFoundError(var3.getMessage()); } } } } |
了解一下Proxy类
java.lang.reflect
Class Proxy
-
public class Proxy extends Object implements Serializable
-
-
Fields Modifier and Type Field and Description protected InvocationHandler
h
the invocation handler for this proxy instance.
-
Constructor Summary
Constructors Modifier Constructor and Description protected
Proxy(InvocationHandler h)
Constructs a new
Proxy
instance from a subclass (typically, a dynamic proxy class) with the specified value for its invocation handler.
-
Method Summary
All Methods Static Methods Concrete Methods Modifier and Type Method and Description static InvocationHandler
getInvocationHandler(Object proxy)
Returns the invocation handler for the specified proxy instance.
返回指定代理实例的调用处理程序。
static Class<?>
getProxyClass(ClassLoader loader, Class<?>... interfaces)
Returns the
java.lang.Class
object for a proxy class given a class loader and an array of interfaces.给定类加载器和接口数组,返回代理类的java.lang.Class对象。
static boolean
isProxyClass(Class<?> cl)
Returns true if and only if the specified class was dynamically generated to be a proxy class using the
getProxyClass
method or thenewProxyInstance
method.当且仅当使用getProxyClass方法或newProxyInstance方法将指定的类动态生成为代理类时,才返回true。
static Object
newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
Returns an instance of a proxy class for the specified interfaces that dispatches method invocations to the specified invocation handler.
返回指定接口的代理类的实例,该实例将方法调用分派到指定的调用处理程序。
-
Proxy源码分析
1 Proxy类的静态方法newProxyInstance方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | 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<Void>() { public Void run() { cons.setAccessible(true); return null; } }); } //传入InvocationHandler实例去构造一个代理类的实例,所有代理类都继承自Proxy,而Proxy构造方法需要InvocationHandler实例作为参数 return cons.newInstance(new Object[]{h}); } catch (IllegalAccessException|InstantiationException e) { throw new InternalError(e.toString(), e); } catch (InvocationTargetException e) { Throwable t = e.getCause(); if (t instanceof RuntimeException) { throw (RuntimeException) t; } else { throw new InternalError(t.toString(), t); } } catch (NoSuchMethodException e) { throw new InternalError(e.toString(), e); } |
从newProxyInstance方法看出,产生代理类核心代码在getProxyClass0
2 Proxy类的静态方法getProxyClass0方法
1 2 3 4 5 6 7 8 9 10 11 12 | private static Class<?> getProxyClass0(ClassLoader loader, Class<?>... interfaces) { if (interfaces.length > 65535) { throw new IllegalArgumentException("interface limit exceeded"); } // If the proxy class defined by the given loader implementing // the given interfaces exists, this will simply return the cached copy; // otherwise, it will create the proxy class via the ProxyClassFactory //如果由实现给定接口的代理类存在,这将简单地返回缓存的副本;否则,将通过ProxyClassFactory创建代理类 return proxyClassCache.get(loader, interfaces); } |
getProxyClass0通过类加载器和接口集合去缓存里面获取,如果能找到代理类就直接返回,否则就会调用ProxyClassFactory这个工厂去生成一个代理类,下面我们看下Proxy的静态内部类ProxyClassFactory
1 private static final class ProxyClassFactory
2 implements BiFunction<ClassLoader, Class<?>[], Class<?>>
3 {
4 // prefix for all proxy class names 代理类名称前缀
5 private static final String proxyClassNamePrefix = "$Proxy";
6
7 // next number to use for generation of unique proxy class names, 用原子类来生成代理类的序号, 保证序号唯一
8 private static final AtomicLong nextUniqueNumber = new AtomicLong();
9
10 @Override
11 public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {
12
13 Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
14 for (Class<?> intf : interfaces) {
15 /*
16 * Verify that the class loader resolves the name of this
17 * interface to the same Class object.
18 */
19 Class<?> interfaceClass = null;
20 try {
21 interfaceClass = Class.forName(intf.getName(), false, loader);
22 } catch (ClassNotFoundException e) {
23 }
24 //intf是否可以由指定的类加载进行加载
25 if (interfaceClass != intf) {
26 throw new IllegalArgumentException(
27 intf + " is not visible from class loader");
28 }
29 /*
30 * Verify that the Class object actually represents an
31 * interface.
32 * intf是否是一个接口
33 */
34 if (!interfaceClass.isInterface()) {
35 throw new IllegalArgumentException(
36 interfaceClass.getName() + " is not an interface");
37 }
38 /*
39 * Verify that this interface is not a duplicate.
40 * intf在数组中是否有重复
41 */
42 if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) {
43 throw new IllegalArgumentException(
44 "repeated interface: " + interfaceClass.getName());
45 }
46 }
47 // package to define proxy class in 生成代理类的包名
48 String proxyPkg = null;
49 // 代理类的访问标志, 默认是public final
50 int accessFlags = Modifier.PUBLIC | Modifier.FINAL;
51
52 /*
53 * Record the package of a non-public proxy interface so that the
54 * proxy class will be defined in the same package. Verify that
55 * all non-public proxy interfaces are in the same package.
56 * 验证所有非公共代理接口都在同一个包中
57 */
58 for (Class<?> intf : interfaces) {
59 //获取接口的访问标志
60 int flags = intf.getModifiers();
61 //如果接口的访问标志不是public, 那么生成代理类的包名和接口包名相同
62 if (!Modifier.isPublic(flags)) {
63 //生成的代理类的访问标志设置改为final
64 accessFlags = Modifier.FINAL;
65 String name = intf.getName();
66 int n = name.lastIndexOf('.');
67 String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
68 if (proxyPkg == null) {
69 proxyPkg = pkg;
70 } else if (!pkg.equals(proxyPkg)) {
71 //代理类如果实现不同包的接口, 并且接口都不是public的, 那么就会在这里报错
72 throw new IllegalArgumentException(
73 "non-public interfaces from different packages");
74 }
75 }
76 }
77
78 if (proxyPkg == null) {
79 // if no non-public proxy interfaces, use com.sun.proxy package 如果没有非公共代理接口,那生成的代理类都放到默认的包下:com.sun.proxy
80 proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
81 }
82
83 /*
84 * Choose a name for the proxy class to generate.
85 * 生成代理类的全限定名, 包名+前缀+序号, 例如:com.sun.proxy.$Proxy0
86 */
87 long num = nextUniqueNumber.getAndIncrement();
88 String proxyName = proxyPkg + proxyClassNamePrefix + num;
89
90 /*
91 * Generate the specified proxy class.
92 * 这里是核心, 用ProxyGenerator来生成字节码, 该类放在sun.misc包下
93 */
94 byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
95 proxyName, interfaces, accessFlags);
96 //根据二进制文件生成相应的Class实例
97 try {
98 return defineClass0(loader, proxyName,
99 proxyClassFile, 0, proxyClassFile.length);
100 } catch (ClassFormatError e) {
101 /*
102 * A ClassFormatError here means that (barring bugs in the
103 * proxy class generation code) there was some other
104 * invalid aspect of the arguments supplied to the proxy
105 * class creation (such as virtual machine limitations
106 * exceeded).
107 */
108 throw new IllegalArgumentException(e.toString());
109 }
110 }
111 }
ProxyClassFactory
ProxyClassFactory中生成代理类核心代码 byte[] proxyClassFile = ProxyGenerator.generateProxyClass(proxyName, interfaces, accessFlags);下面我们继续分析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 }
generateProxyClass
跟踪了这么久源码,终极代码终于出现了,下面我们分析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 < var2; ++var3) {
14 var4 = var1[var3];
15 Method[] var5 = var4.getMethods();
16 int var6 = var5.length;
17
18 for(int var7 = 0; var7 < var6; ++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 < var2; ++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 < var18; ++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 }
generateClassFile
动态代理的本质:通过类加载器获取类字节码,通过类实现的接口反射获得该类的属性,方法等,并生成新的字节码文件