设为首页 加入收藏

TOP

不是单例的单例——巧用ClassLoader(三)
2023-07-25 21:25:11 】 浏览:57
Tags:单例的 单例 巧用 ClassLoader
程序的全局范围内都没有设置过的话,那这个类加载器默认就是 AppClassLoader。
有了线程上下文类加载器,程序就可以做一些 “舞弊”的事情了。JNDI 服务使用这个线程上下文类加载器去加载所需的 SPI 服务代码,这是一种父类加载器去请求子类加载器完成类加载的行为,这种行为实际上是打通了双亲委派模型的层次结构来逆向使用类加载器,已经违背了双亲委派模型的一般性原则,但也是无可奈何的事情。Java 中涉及 SPI 的加载基本上都采用这种方式来完成的。

可以通过如下的代码来获取当前线程的 ContextClassLoader :

ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();

我们在前面测试代码中将 Thread Context ClassLoader 也设置为自定义加载器,目的是避免自定义加载器加载的类里面使用了 Thread Context ClassLoader(默认是 AppClassLoader),导致对象没有完全完全隔离,这也是自定义加载器的常用原则之一。在自定义加载器加载完成之后也要将 Thread Context ClassLoader 复原:

//实例化自定义类加载器
MyClassLoader myClassLoader = new MyClassLoader();
//获取当前线程的 ContextClassLoader 备用
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
//设置当前线程的 ContextClassLoader 为实例化的自定义类加载器(这么做的原因下文会补充)
Thread.currentThread().setContextClassLoader(myClassLoader);
//通过自定义类加载器加载 RPCClient
Class<?> rpcClientCls = myClassLoader.loadClass("com.ppphuang.demo.classloader.single.RPCClient");
//将当前线程的 ContextClassLoader 还原为初始的 contextClassLoader
Thread.currentThread().setContextClassLoader(contextClassLoader);

Tomcat类加载模型

提到破坏双亲委派模型就必须要提到 Tomcat,部署在一个 Tomcat 中的每个应用程序都会有一个独一无二的 webapp classloader,他们互相隔离不受彼此的影响。除了互相隔离的类加载器,Tomcat 中还有共享的类加载器,大家可以去查看一下相关的文档,还是很值得我们借鉴学习的。

看到这里再回头来理解上文自定义类加载器实例化单例类的代码,应该就很好理解了。

总结

本文通过如何将一个单例类实例化两次的案例,用代码实践来引入 Java 类加载器相关的概念与工作机制。理解并熟练掌握相关知识之后可以扩宽解决问题的思路,另辟蹊径,达到目的。

参考

https://blog.csdn.net/qq_43369986/article/details/117048340

https://blog.csdn.net/qq_40378034/article/details/119973663

https://blog.csdn.net/J080624/article/details/84835493

公众号:DailyHappy 一位后端写码师,一位黑暗料理制造者。

首页 上一页 1 2 3 4 下一页 尾页 3/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Springboot通过谷歌Kaptcha 组件.. 下一篇SpringBoot 使用 Sa-Token 完成注..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目