下述所有类均定义在包structure.proxy.dynamicproxy
中。
public interface AbstractUserDAO {
Boolean findUserById(String userId);
}
public class UserDAO implements AbstractUserDAO {
@Override
public Boolean findUserById(String userId) {
System.out.println("findUserById" + userId);
return true;
}
}
public class DAOLogHandler implements InvocationHandler {
private Object object;
public DAOLogHandler(Object object) {
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getName().equals("findUserById")) {
System.out.println("before invoke");
}
Object result = method.invoke(object, args);
if (method.getName().equals("findUserById")) {
System.out.println("after invoke");
}
return result;
}
}
public class Test {
public static void main(String[] args) {
AbstractUserDAO userDAO = new UserDAO();
InvocationHandler handler = new DAOLogHandler(userDAO);
AbstractUserDAO proxy = (AbstractUserDAO) Proxy.newProxyInstance(AbstractUserDAO.class.getClassLoader(),
new Class[] {AbstractUserDAO.class}, handler);
System.out.println(Objects.equals(userDAO, proxy));
System.out.println("userDAO = " + userDAO);
System.out.println("proxy = " + proxy);
System.out.println("userDAO.getClass() = " + userDAO.getClass());
System.out.println("proxy.getClass() = " + proxy.getClass());
System.out.println("userDAO.hashCode() = " + userDAO.hashCode());
System.out.println("proxy.hashCode() = " + proxy.hashCode());
}
}
false
userDAO = structure.proxy.dynamicproxy.UserDAO@2b193f2d
proxy = structure.proxy.dynamicproxy.UserDAO@2b193f2d
userDAO.getClass() = class structure.proxy.dynamicproxy.UserDAO
proxy.getClass() = class com.sun.proxy.$Proxy0
userDAO.hashCode() = 723074861
proxy.hashCode() = 723074861
proxy
和目标对象userDAO
并不是同一个对象,但是它们的hashCode()
方法和toString()
方法的结果均相同,这是因为JDK动态代理只对接口中声明的方法进行代理,hashCode()
方法和toString()
方法是在Object
中定义的,不会被代理对象拦截。getClass()
方法返回的是对象的运行时类型信息,可以看到,代理对象proxy
的类型是class com.sun.proxy.$Proxy0
,而目标对象userDAO
的类型是structure.proxy.dynamicproxy.UserDAO
。.class
文件public class Test {
public static void main(String[] args) throws IOException {
AbstractUserDAO userDAO = new UserDAO();
byte[] bytes = ProxyGenerator.generateProxyClass("$Proxy0", new Class[]{userDAO.getClass()});
FileOutputStream os = new FileOutputStream("Proxy0.class");
os.write(bytes);
os.close();
}
}
Proxy0.class
文件import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
import structure.proxy.dynamicproxy.UserDAO;
public final class $Proxy0 extends Proxy implements UserDAO {
private static Method m1;
private static Method m8;
private static Method m2;
private static Method m5;
private static Method m3;
private static Method m4;
private static Method m7;
private static Method m9;
private static Method m0;
private static Method m6;
public $Proxy0(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 void notify() throws {
try {
super.h.invoke(this, m8, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
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 wait(long var1) throws InterruptedException {
try {
super.h.invoke(this, m5, new Object[]{var1});
} catch (RuntimeException | InterruptedException | Error var4) {
throw var4;
} catch (Throwable var5) {
throw new UndeclaredThrowableException(var5);
}
}
public final Boolean findUserById(String var1) throws {
try {
return (Boolean)super.h.invoke(this, m3, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
public final void wait(long var1, int var3) throws InterruptedException {
try {
super.h.invoke(this, m4, new Object[]{var1, var3});
} catch (RuntimeException | InterruptedException | Error var5) {
throw var5;
} catch (Throwable var6) {
throw new UndeclaredThrowableException(var6);
}
}
public final Class getClass() throws {
try {
return (Class)super.h.invoke(this, m7, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final void notifyAll() throws {
try {
super.h.invoke(this, m9, (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);
}
}
public final void wait() throws InterruptedException {
try {
super.h.invoke(this, m6, (Object[])null);
} catch (RuntimeException | InterruptedException | 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"));
m8 = Class.forName("structure.proxy.dynamicproxy.UserDAO").getMethod("notify");
m2 = Class.forName("java.lang.Object").getMethod("toString");
m5 = Class.forName("structure.proxy.dynamicproxy.UserDAO").getMethod("wait", Long.TYPE);
m3 = Class.forName("structure.proxy.dynamicproxy.UserDAO").getMethod("findUserById", Class.forName("java.lang.String"));
m4 = Class.forName("structure.proxy.dynamicproxy.UserDAO").getMethod("wait", Long.TYPE, Integer.TYPE);
m7 = Class.forName("structure.proxy.dynamicproxy.UserDAO").getMethod("getClass");
m9 = Class.forName("structure.proxy.dynamicproxy.UserDAO").getMethod("notifyAll");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
m6 = Class.forName("structure.proxy.dynamicproxy.UserDAO").getMethod("wait");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
上述代码中可以看到$Proxy0
已经继承了Proxy
类,由于Java只允许单继承,故只能对接口进行动态代理。