- 原始方法1
- @return String
*/
String doSomething();
int printNum();
}
目标类:
public class Target implements TargetInterface {
@Override
public String doSomething() {
System.out.println(“doSomething”);
return “doSomething”;
}
@Override
public int printNum() {
System.out.println(“printNum”);
return 100;
}
}
- 代理类逻辑处理:(不是真正的代理类)
public class DynamicProxyHandler implements InvocationHandler {
private final Object target;
public DynamicProxyHandler(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;
}
}
- 动态代理对象生成:
mport java.lang.reflect.Proxy;
public class ProxyTest {
public static void main(String[] args) {
//1、创建被代理的目标对象
Target target = new Target();
//2、创建代理类处理器对象
DynamicProxyHandler dynamicProxyHandler = new DynamicProxyHandler(target);
//3、创建代理类对象
//a.JDK会通过传入的参数信息动态地在内存中创建和.class文件等同的字节码
//b.然后会根据相应的字节码转换成对应的class
//c.最后创建代理类实例
TargetInterface proxy = (TargetInterface) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), dynamicProxyHandler);
System.out.println(“doSomething() call: " + proxy.doSomething());
System.out.println(”------------------------");
System.out.println("proxy.printNum() call: " + proxy.printNum());
}
}
- 输出结果:
doSomething
do something after
doSomething() call: doSomething
do something before
printNum
do something after
proxy.printNum() call: 100
- 具体步骤
- 通过实现InvovationHandler接口创建自己的调用处理器
- 通过为Proxy类指定ClassLoader对象和一组Interface来创建动态代理类
- 通过反射机制获取动态代理类的构造
【一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义】 浏览器打开:qq.cn.hn/FTf 免费领取
函数,其唯一参数类型是InvocationHandler接口类型
4. 通过构造函数创建动态代理类实例,调用处理器对象(InvocationHandler接口的实现类实例)作为参数传入
- Proxy类分析
public class Proxy implements java.io.Serializable {
@CallerSensitive
public static Object newProxyInstance(ClassLoader loader,
Class>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException {
Objects.requireNonNull(h);
final Class>[] intfs = interfaces.clone();
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
}
Class> cl = getProxyClass0(loader, intfs);
try {
if (sm != null) {
checkNewProxyPermission(Reflection.getCallerClass(), cl);
}
final Constructor> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h;
return cons.newInstance(new Object[]{h});
} catch (IllegalAccessException|InstantiationException e) {
throw new InternalError(e.toString(), e);
} catch (InvocationTargetException e) {
Throwable t = e.getCause();
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
} else {
throw new InternalError(t.toString(), t);
}
} catch (NoSuchMethodException e) {
throw new InternalError(e.toString(), e);
}
}
}
private static Class> getProxyClass0(ClassLoader loader,
Class>… interfaces) {
if (interfaces.length > 65535) {
throw new IllegalArgumentException(“interface limit exceeded”);
}
// 如果实现指定接口的代理类存在于指定加载器中,则直接返回缓存副本
// 否则通过ProxyClassFactory创建代理类
return proxyClassCache.get(loader, interfaces);
}
- ProxyClassFactory类生成代理类
简单步骤就是先生成类的字节码文件,再通过Proxy类的defineClass0本地方法生成字节码文件。具体实现代码可以查看Proxy类的静态内部类ProxyClassFactory源码。
- 字节码文件
System.getProperties().setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");方法修改系统变量,可以保存生成的字节码文件
字节码文件:
actory源码**。
- 字节码文件
System.getProperties().setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");方法修改系统变量,可以保存生成的字节码文件
[外链图片转存中…(img-06Y4pLMU-1636272455512)]
字节码文件:



