动态代理是在运行时,通过反射机制实现动态代理,并且能够代理各种类型的对象。相对于静态代理,它的优势是不需要事先知道被代理的类型,可以与被代理的类解耦,同时可以大大减少代理类的数量。

JDK动态代理的例子

Subject.java

1	package test.proxy;
2
3	public interface Subject {
4		int doSomething();
5	}

RealSubject.java

1	package test.proxy;
2
3	public class RealSubject implements Subject {
4		@Override
5		public int doSomething() {
6			System.out.println("RealSubject do something");
7			return 10;
8		}
9	}

ProxyHandler.java

 1	package test.proxy;
 2
 3	import java.lang.reflect.InvocationHandler;
 4	import java.lang.reflect.Method;
 5
 6	public class ProxyHandler implements InvocationHandler {
 7		private Object source;
 8		public ProxyHandler(Object obj) {
 9			this.source = obj;
10		}
11
12		@Override
13		public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
14			System.out.println("Before");
15			Object r = method.invoke(this.source, args);
16			System.out.println("End");
17			return r;
18		}
19	}

调用类的实现:

 1	package test.proxy;
 2
 3	import java.lang.reflect.Proxy;
 4
 5	public class TestProxy {
 6		public static void main(String[] args) {
 7			RealSubject realSubject = new RealSubject();
 8			Subject subject = (Subject) Proxy.newProxyInstance(realSubject.getClass().getClassLoader(), realSubject.getClass().getInterfaces(), new ProxyHandler(realSubject));
 9			int result = subject.doSomething();
10			System.out.println(result);
11		}
12	}

输出结果:

1Before
2RealSubject do something
3End
410
5
6Process finished with exit code 0

通过加入如下属性System.getProperties().put(“sun.misc.ProxyGenerator.saveGeneratedFiles”, “true”);,可以将动态生成的代理类保存到磁盘,得到的动态代理类文件反编译得到如下:

 1	//
 2	// Source code recreated from a .class file by IntelliJ IDEA
 3	// (powered by Fernflower decompiler)
 4	//
 5
 6	package com.sun.proxy;
 7
 8	import java.lang.reflect.InvocationHandler;
 9	import java.lang.reflect.Method;
10	import java.lang.reflect.Proxy;
11	import java.lang.reflect.UndeclaredThrowableException;
12	import test.proxy.Subject;
13
14	public final class $Proxy0 extends Proxy implements Subject {
15		private static Method m1;
16		private static Method m3;
17		private static Method m2;
18		private static Method m0;
19
20		public $Proxy0(InvocationHandler var1) throws  {
21			super(var1);
22		}
23
24		public final boolean equals(Object var1) throws  {
25			try {
26				return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
27			} catch (RuntimeException | Error var3) {
28				throw var3;
29			} catch (Throwable var4) {
30				throw new UndeclaredThrowableException(var4);
31			}
32		}
33
34		public final int doSomething() throws  {
35			try {
36				return (Integer)super.h.invoke(this, m3, (Object[])null);
37			} catch (RuntimeException | Error var2) {
38				throw var2;
39			} catch (Throwable var3) {
40				throw new UndeclaredThrowableException(var3);
41			}
42		}
43
44		public final String toString() throws  {
45			try {
46				return (String)super.h.invoke(this, m2, (Object[])null);
47			} catch (RuntimeException | Error var2) {
48				throw var2;
49			} catch (Throwable var3) {
50				throw new UndeclaredThrowableException(var3);
51			}
52		}
53
54		public final int hashCode() throws  {
55			try {
56				return (Integer)super.h.invoke(this, m0, (Object[])null);
57			} catch (RuntimeException | Error var2) {
58				throw var2;
59			} catch (Throwable var3) {
60				throw new UndeclaredThrowableException(var3);
61			}
62		}
63
64		static {
65			try {
66				m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
67				m3 = Class.forName("test.proxy.Subject").getMethod("doSomething");
68				m2 = Class.forName("java.lang.Object").getMethod("toString");
69				m0 = Class.forName("java.lang.Object").getMethod("hashCode");
70			} catch (NoSuchMethodException var2) {
71				throw new NoSuchMethodError(var2.getMessage());
72			} catch (ClassNotFoundException var3) {
73				throw new NoClassDefFoundError(var3.getMessage());
74			}
75		}
76	}