马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
x
本文侧重分析JDK8中jdk动态代理的源码,若是想看JDK17源码分析可以看我的这一篇文章 JDK17源码分析Jdk动态代理底层原理-CSDN博客
两者之间有着略微的差别,JDK17在JDK8上改进了不少
目录
源码分析
过程
生成的代理类大致结构
本文侧重分析JDK8中jdk动态代理的源码,若是想看JDK17源码分析可以看我的这一篇文章 JDK17源码分析Jdk动态代理底层原理-CSDN博客
两者之间有着略微的差别,JDK17在JDK8上改进了不少
InvocationHandler最终存储在代理类实例的h字段中,这个字段是从Proxy类继承的。当调用代理对象的方法时,会调用这个h字段引用的InvocationHandler实例的invoke方法。如许就实现了方法调用的拦截和处置惩罚。
源码分析
- public class Proxy implements java.io.Serializable {
- /**
- * InvocationHandler对象,用于处理代理类的方法调用
- * 这个字段会被所有代理类继承,存储在代理类实例中
- */
- protected InvocationHandler h;
-
- /**
- * 代理类的构造函数,将InvocationHandler传递给代理类实例
- * 这个构造函数会被所有代理类调用
- */
- protected Proxy(InvocationHandler h) {
- Objects.requireNonNull(h);
- this.h = h;
- }
- /**
- * 创建代理类实例的核心方法
- * loader: 类加载器,用于加载代理类
- * interfaces: 代理类需要实现的接口数组
- * h: 调用处理器,用于处理代理类的方法调用
- */
- @CallerSensitive
- public static Object newProxyInstance(ClassLoader loader,
- Class<?>[] interfaces,
- InvocationHandler h) {
- // 检查InvocationHandler是否为空
- 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;
-
- // 如果构造函数是非public的,设置其可访问
- if (!Modifier.isPublic(cl.getModifiers())) {
- AccessController.doPrivileged(new PrivilegedAction<Void>() {
- public Void run() {
- cons.setAccessible(true);
- return null;
- }
- });
- }
-
- // 创建代理类实例
- return cons.newInstance(new Object[]{h});
-
- } catch (IllegalAccessException|InstantiationException e) {
- throw new InternalError(e.toString(), e);
- } catch (InvocationTargetException e) {
- throw new InternalError(e.toString(), e);
- } catch (NoSuchMethodException e) {
- throw new InternalError(e.toString(), e);
- }
- }
- /**
- * 获取代理类的核心方法
- * 这个方法会调用ProxyClassFactory来生成代理类
- */
- private static Class<?> getProxyClass0(ClassLoader loader,
- Class<?>[] interfaces) {
- // 如果接口数量超过65535,抛出异常
- if (interfaces.length > 65535) {
- throw new IllegalArgumentException("interface limit exceeded");
- }
- // 从缓存中获取代理类,如果不存在则生成
- return proxyClassCache.get(loader, interfaces);
- }
- }
- /**
- * 代理类工厂,负责生成代理类的字节码
- */
- private static final class ProxyClassFactory
- implements BiFunction<ClassLoader, Class<?>[], Class<?>> {
-
- // 代理类名称前缀
- private static final String proxyClassNamePrefix = "$Proxy";
- // 原子计数器,用于生成唯一的代理类名
- private static final AtomicLong nextUniqueNumber = new AtomicLong();
- @Override
- public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {
- Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
-
- // 验证接口
- for (Class<?> intf : interfaces) {
- // 验证类加载器能否加载这个接口
- validateInterface(intf, loader, interfaceSet);
- }
- // 生成代理类的名称
- String proxyPkg = null; // 包名
- int accessFlags = Modifier.PUBLIC | Modifier.FINAL;
- // 检查所有非公共接口是否在同一个包中
- for (Class<?> intf : interfaces) {
- int flags = intf.getModifiers();
- if (!Modifier.isPublic(flags)) {
- accessFlags = Modifier.FINAL; // 移除public标志
- String pkg = intf.getPackageName();
- if (proxyPkg == null) {
- proxyPkg = pkg;
- } else if (!pkg.equals(proxyPkg)) {
- throw new IllegalArgumentException(
- "non-public interfaces from different packages");
- }
- }
- }
- // 如果没有指定包名,默认使用com.sun.proxy
- if (proxyPkg == null) {
- proxyPkg = "com.sun.proxy";
- }
- // 生成代理类的完整名称
- long num = nextUniqueNumber.getAndIncrement();
- String proxyName = proxyPkg.isEmpty()
- ? proxyClassNamePrefix + num
- : proxyPkg + "." + proxyClassNamePrefix + num;
- // 生成代理类的字节码
- byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
- proxyName, interfaces, accessFlags);
- try {
- // 加载代理类
- return defineClass0(loader, proxyName,
- proxyClassFile, 0, proxyClassFile.length);
- } catch (ClassFormatError e) {
- throw new IllegalArgumentException(e.toString());
- }
- }
- }
复制代码 过程
JDK动态代理生成代理对象的过程可以分为以下几个关键步调:
1.调用Proxy.newProxyInstance方法,传入类加载器、接口数组和InvocationHandler实例。这是整个代理创建过程的入口。
2.通过getProxyClass0方法获取代理类。这个方法会首先查抄缓存中是否已经存在对应的代理类,如果不存在则创建新的代理类。
3.ProxyClassFactory负责生成代理类的字节码,此中会,验证接口的合法性,生成唯一的代理类名,确定代理类的包名,调用ProxyGenerator生成字节码
4. 获取代理类的构造函数,这个构造函数吸取一个InvocationHandler参数。
5.使用构造函数创建代理类实例,将InvocationHandler传入。这个InvocationHandler会被存储在代理类的h字段中。
生成的代理类大致结构
- public final class $Proxy0 extends Proxy implements UserService {
-
-
- // 静态方法对象,用于方法调用
- private static Method m1;
- private static Method m2;
- private static Method m3;
-
- static {
- try {
- // 初始化方法对象
- m1 = Class.forName("java.lang.Object")
- .getMethod("equals", Object.class);
- m2 = Class.forName("com.example.UserService")
- .getMethod("addUser", String.class);
- // ... 其他方法
- } catch (NoSuchMethodException e) {
- throw new NoSuchMethodError(e.getMessage());
- }
- }
-
- // 构造函数,调用父类构造函数存储InvocationHandler
- public $Proxy0(InvocationHandler h) {
- super(h);
- }
-
- // 实现接口方法
- @Override
- public void addUser(String name) {
- try {
- // 调用InvocationHandler的invoke方法
- h.invoke(this, m2, new Object[]{name});
- } catch (Throwable e) {
- throw new UndeclaredThrowableException(e);
- }
- }
- }
复制代码 InvocationHandler最终存储在代理类实例的h字段中,这个字段是从Proxy类继承的。当调用代理对象的方法时,会调用这个h字段引用的InvocationHandler实例的invoke方法。如许就实现了方法调用的拦截和处置惩罚。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |