什么是JDK动态代理
(有动态代理,就有静态代理,参见:多线程03--静态代理模式_runnable接口静态代理模式-优快云博客)
JDK动态代理是Java提供的一种动态生成代理对象的机制,允许在运行时创建一个实现了指定接口的代理类。它主要用于在不修改目标对象的情况下,为目标对象添加额外的功能,比如日志记录、权限检查、事务管理等。
编码实现
代码比较简单,但核心的步骤及实现细节都有,主要分析在后面。
定义一个顶层接口
package com.ldzn.normal.proxy.dynamic;
/**
* @FileName: IService
* @Description: 基类接口
* @Author: liulianglin
* @Date: 2024/11/26:11:32
*/
public interface IService {
void myselfMethod();
}
被代理的对象
package com.ldzn.normal.proxy.dynamic;
/**
* @FileName: RealObjectService
* @Description: 真的对象服务
* @Author: liulianglin
* @Date: 2024/11/26:11:33
*/
public class RealObjectService implements IService{
@Override
public void myselfMethod() {
System.out.println("RealObjectService test .......");
}
}
自定义个动态代理处理类
package com.ldzn.normal.proxy.dynamic;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* @FileName: DynamicInvocationHandler
* @Description: 动态代理处理类
* @Author: liulianglin
* @Date: 2024/11/26:11:34
*
* 1.拿到被代理对象的引用,然后获取它的接口
* 2.jdk代理重新生成一个类,同时实现我们个额的代理对象所实现的接口
* 3.把被代理对象的引用也拿到了
* 4.重新动态生成一个class字节码
* 5.然后编译
*
*/
public class DynamicInvocationHandler implements InvocationHandler {
private Object target;
public Object getInstance(IService target) throws Exception {
this.target = target;
Class clazz = target.getClass();
System.out.println("被代理对象的class是:"+ clazz);
return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("开始进行方法增强,(记录日志、校验、性能统计等),,,,");
Object result = method.invoke(target, args);
System.out.println("方法增强完毕,(记录日志、校验、性能统计等),,,,,");
return result;
}
}
测试调用
package com.ldzn.normal.proxy.dynamic;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Executable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* @FileName: MainTest
* @Description:
* @Author: liulianglin
* @Date: 2024/11/26:12:10
*/
public class MainTest {
public static void printClassInfo(Executable[] targets) {
for (Executable target : targets) {
// 构造器/方法名称
String name = target.getName();
StringBuilder sBuilder = new StringBuilder(name);
// 拼接左括号
sBuilder.append('(');
Class<?>[] clazzParams = target.getParameterTypes();
// 拼接参数
for (Class<?> clazzParam : clazzParams) {
sBuilder.append(clazzParam.getName()).append(',');
}
//删除最后一个参数的逗号
if (clazzParams.length != 0) {
sBuilder.deleteCharAt(sBuilder.length() - 1);
}
//拼接右括号
sBuilder.append(')');
//打印 构造器/方法
System.out.println(sBuilder.toString());
}
}
/**
* 将动态代理生成的代理类的字节码保存到本地磁盘,方便调试查看
* @param path
* @throws ClassNotFoundException
* @throws NoSuchMethodException
* @throws InvocationTargetException
* @throws IllegalAccessException
* @throws IOException
*/
public static void saveProxyClassFile(String path) {
Class cl = null;
FileOutputStream fileOutputStream = null;
try {
// Java11开始ProxyGenerator,不再public,改为了private,无法直接使用,所以采用反射的方式获取它
cl = Class.forName("java.lang.reflect.ProxyGenerator");
Method m =cl.getDeclaredMethod("generateProxyClass",String.class,Class[].class);
m.setAccessible(true);
byte[] $proxy1 = (byte[]) m.invoke(null, "$proxy1",
RealObjectService.class.getInterfaces());
System.out.println($proxy1.length);
fileOutputStream = new FileOutputStream((path + "$Proxy.class"));
fileOutputStream.write($proxy1);
}catch (ClassNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
} catch (Exception e){
e.printStackTrace();
} finally {
if (fileOutputStream !=

最低0.47元/天 解锁文章
768

被折叠的 条评论
为什么被折叠?



