之前虽然会使用JDK的动态代理,但是有些问题始终没有搞明白。比如说:InvocationHandler的invoke方法是由谁来调用的?代理对象是怎么生成的?今天就搞明白吧。
1 JDK动态代理的使用
接口:
package designpattern.proxy.userproxy;
public interface UserService {
void add();
}
实现:
package designpattern.proxy.userproxy;
public class UserServiceImpl implements UserService {
@Override
public void add() {
System.out.println("----------add----------");
}
}
使用实例:
package designpattern.proxy.userproxy;
import sun.misc.ProxyGenerator;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class MyInvocationHandler<T> implements InvocationHandler {
private T target;
MyInvocationHandler (T o) {
super();
this.target = o;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 将代理对象生成字节码到D:\Workspace
addClassToDisk(proxy.getClass().getName(), target.getClass(), "D:\Workspace\targetProxy.class");
System.out.println("方法" + method.getName() + "执行前!");
Object invokeResult = method.invoke(target, args);
System.out.println("方法" + method.getName() + "执行后!");
return invokeResult;
}
public T getProxy() {
ClassLoader classLoader = target.getClass().getClassLoader();
Class<?>[] intfs = target.getClass().getInterfaces();
return (T) Proxy.newProxyInstance(classLoader, intfs, this);
}
private void addClassToDisk(String className, Class<?> cl, String path) {
// JDK底层即使通过这个方法生成代理对象的.class字节码文件
byte[] bytes = ProxyGenerator.generateProxyClass(className, cl.getInterfaces());
FileOutputStream outputStream = null;
try {
outputStream = new FileOutputStream(path);
outputStream.write(bytes);
outputStream.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
2 JDK生成代理对象类的.class字节码文件
JDK底层通过ProxyGenerator.generateProxyClass(className, cl.getInterfaces())创建代理对象类的.class字节码文件
测试用例:
@org.junit.Test
public void test_JDKProxy() {
// 实例化目标对象
UserService userService = new UserServiceImpl();
// 实例化InvocationHandler,传入被代理的目标对象
MyInvocationHandler<UserService> myInvocationHandler = new MyInvocationHandler(userService);
// 根据传入的被代理对象,生成代理对象
UserService userServiceProxy = myInvocationHandler.getProxy();
System.out.println(Proxy.isProxyClass(userServiceProxy.getClass()));
// 调用代理对象的方法
userServiceProxy.add();
}
3 动态代理类
动态代理对象类的字节码(.class文件)反编译后:
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package com.sun.proxy;
import designpattern.proxy.userproxy.UserService;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
public final class $Proxy4 extends Proxy implements UserService {
private static Method m1;
private static Method m2;
private static Method m3;
private static Method m0;
// 通过这个构造方法创建代理对象实例
public $Proxy4(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 add() 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("designpattern.proxy.userproxy.UserService").getMethod("add");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
生成的代理对象实现了接口的所有方法(接口定义的add()方法和equals(Object var1)、hashCode()、toString())。调用代理对象实现的所有接口方法,都会交给InvocationHandler.invoke()方法处理。
4 生成代理对象
代理对象类的class对象创建代理对象,构造方法的参数即为传进来的InvocationHandler,每个代理对象都从父类Proxy继承了一个InvocationHandler