JDK动态代理源码
一、public static Object newProxyInstance ——> 调用下面这个方法
二、Class<?> cl = getProxyClass0(loader, intfs); ——> 这个方法从下面这个缓存对象中返回代理类Class对象
三、return proxyClassCache.get(loader, interfaces); ——> 这个缓存对象是一个成员变量
四、proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory()); ——> 打开ProxyClassFactory这个类
五、private static final class ProxyClassFactory ——> 这是Proxy的一个内部类
六、public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) { ——> 该内部类有一个apply方法,查看apply方法
1、确定代理类的名称
(2)确定代理类包名:得到传入接口的全限定名,截取接口包名作为代理类的包名;如果接口没有包名,把包名设置为com.sun.proxy
(3)确定代理类类名:类名前缀为§Proxy;后面加一个递增的数字,从0开始,如第一个代理类的名称为§Proxy0
(4)把代理类的包名和类名拼接起来
2、生成代理类字节码文件
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(proxyName, interfaces); ——> 打开generateProxyClass()方法,查看generateClassFile()方法
七、generateClassFile() ——>
1、生成hashCode、equals、toString方法
2、生成构造方法,this.methods.add(this.generateConstructor());
3、生成接口里的方法private ProxyGenerator.MethodInfo generateMethod() throws IOException {
JDK动态代理分析
JDK动态代理在运行期创建接口的代理类并返回代理对象。
InvocationHandler可以看成是一个编织器。
Invocationhandler的invoke(Object proxy, Method method, Object[] args)方法,第一个参数是代理对象,一般不会用到;第二个参数method是JDK通过调用——我们调用Proxy的newProxyInstance方法时传入的第二个接口类型参数——的getMethods得来的;通过反射调用method的invoke方法来调用目标类的代码,将横切逻辑和业务逻辑编织在一起。
InvocationHandler还有一个成员变量,即目标对象,声明为Object类型即可,调用method方法时的invoke方法时要把这个Object传入进去。因为在调用Proxy的静态方法时已经传入了接口,所以JDK会把Object类型的成员变量向下转型为接口类型。
JDK动态代理实现
直接运行下面的代码,在D盘就可以看到生成的源码类$GameProxy.class
import sun.misc.ProxyGenerator; import java.io.File; import java.io.FileOutputStream; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class ViewProxyClass { public static void main(String[] args) throws Exception { Moveable huiXiong = new Tank("灰熊坦克"); ClassLoader classLoader = huiXiong.getClass().getClassLoader(); Class<?>[] interfaces = huiXiong.getClass().getInterfaces(); Moveable proxy = (Moveable) Proxy.newProxyInstance(classLoader, interfaces, new TimeInvocationHandler(huiXiong)); System.out.println(proxy.getClass()); proxy.move(); proxy.stop(); byte[] bts = ProxyGenerator.generateProxyClass("$GameProxy", interfaces); FileOutputStream fos = new FileOutputStream(new File("D:/$GameProxy.class")); fos.write(bts); fos.flush(); fos.close(); } } interface Moveable { public void move(); public void stop(); public String getName(); } class Tank implements Moveable { private String name; public Tank(String name) { this.name = name; } @Override public String getName() { return name; } @Override public void stop() { System.out.println(this.name + " stop ..."); } @Override public void move() { System.out.println(this.name + " run ..."); } } class TimeInvocationHandler implements InvocationHandler { private Object target; public TimeInvocationHandler(Moveable target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("begin"); method.invoke(target, args); System.out.println("end"); return proxy; } }