原文写的的确是nice,但关于源码那块没有时间去读,也没有完全copy过来,有兴趣的可以去原文链接看源码。
案例说明
- 新建一个接口
- 新建一个该接口的实现类
- 新建代理类并实现java.lang.reflect.InvocationHandler接口进行测试
例子
- 新建一个接口UserService,添加两个方法:
package com.example.demo.proxy;
/**
* @Author: pk.zhang
* @Date: 2019/12/13 14:55
*/
public interface UserService {
void addUser(String userName);
void deleteUser(String userName);
}
- 新建接口实现类,如下:
package com.example.demo.proxy;
/**
* @Author: pk.zhang
* @Date: 2019/12/13 14:56
*/
public class UserServiceImpl implements UserService {
@Override
public void addUser(String userName) {
System.out.println("新增用户方法,新增了===" + userName);
}
@Override
public void deleteUser(String userName) {
System.out.println("删除用户方法,删除了===" + userName);
}
}
- 然后 新建代理类并实现java.lang.reflect.InvocationHandler接口进行测试
package com.example.demo.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* 动态代理实现
* @Author: pk.zhang
* @Date: 2019/12/13 14:58
*/
public class JdkProxy implements InvocationHandler {
private Object target;
public JdkProxy(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Do something before");
Object invoke = method.invoke(target, args);
System.out.println("Do something after");
return invoke;
}
public <T> T getJdkProxy(){
return (T)Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
public static void main(String[] args) {
// 保存生成的代理类的字节码文件
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
UserService jdkProxy = new JdkProxy(new UserServiceImpl()).getJdkProxy();
jdkProxy.addUser("张鲜生");
}
}
运行JdkProxy
中的main
函数,控制台输出如下:
Do something before
新增用户方法,新增了===张鲜生
Do something after
由于设置 sun.misc.ProxyGenerator.saveGeneratedFiles
的值为true
,所以代理类的字节码内容保存在了项目根目录下,文件名为$Proxy0.class
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WtEHMCZs-1576224423621)(http://uacoding.cn/images/dayuse/jdk/1.png)]
打开$Proxy0.class文件如下:
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package com.sun.proxy;
import com.example.demo.proxy.UserService;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
public final class $Proxy0 extends Proxy implements UserService {
private static Method m1;
private static Method m3;
private static Method m2;
private static Method m0;
private static Method m4;
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 addUser(String var1) throws {
try {
super.h.invoke(this, m3, 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 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 deleteUser(String var1) throws {
try {
super.h.invoke(this, m4, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m3 = Class.forName("com.example.demo.proxy.UserService").getMethod("addUser", Class.forName("java.lang.String"));
m2 = Class.forName("java.lang.Object").getMethod("toString");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
m4 = Class.forName("com.example.demo.proxy.UserService").getMethod("deleteUser", Class.forName("java.lang.String"));
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
可看到
1、代理类继承了Proxy类并且实现了要代理的接口
,由于java不支持多继承,所以JDK动态代理不能代理类
2、重写了equals、hashCode、toString
3、有一个静态代码块,通过反射或者代理类的所有方法
4、通过invoke
执行代理类中的目标方法