Tomcat与Spring-Web模块加载:SPI机制下的类加载行为分析
Tomcat加载Spring-Web模块时,利用Java SPI(Service Provider Interface)机制查找并使用ServletContainerInitializer接口的实现类。 这涉及到ServiceLoader的load方法和类加载器的可见性原则。 有人质疑这种方式违反了类加载器的可见性原则,让我们深入分析。
文章指出,ServiceLoader.load方法最终由sun.misc.Launcher.AppClassLoader加载ServletContainerInitializer接口的实现类。代码中,ServiceLoader.load(service, cl) 使用Thread.currentThread().getContextClassLoader() 获取类加载器,在Tomcat等应用服务器中,该类加载器通常是AppClassLoader。
有人认为ServiceLoader.load(service, cl) 等同于 ServiceLoader.load(service, null)。虽然在某些情况下结果相似,但原理不同。前者明确指定类加载器,而后者使用调用者的类加载器。
立即学习“Java免费学习笔记(深入)”;
为什么有人认为这破坏了类加载器的可见性原则?关键在于SPI机制的特殊性。rt.jar 中的接口由BootstrapClassLoader加载,但其实现类通常在classpath中,由AppClassLoader加载。BootstrapClassLoader无法向下委托加载,因此需要线程上下文类加载器加载实现类。 这绕过了双亲委派模型的严格层次,使AppClassLoader能够加载BootstrapClassLoader无法加载的类。虽然解决了问题,但也偏离了双亲委派模型的本意。
需要强调的是,AppClassLoader并没有直接跳过双亲委派机制的代码,它内部仍然遵循双亲委派逻辑。只是在SPI场景下,由于BootstrapClassLoader的限制,最终加载工作由AppClassLoader完成,这是一种权衡之举。 JDBC机制类似,Java只提供接口,具体实现由厂商提供,同样需要绕过双亲委派机制的限制。
因此,SPI机制在某种程度上“违反”了双亲委派模型的严格规则,但这是一种必要的妥协,并非完全“破坏”了类加载器的可见性原则。它通过线程上下文类加载器找到了加载实现类的合适途径。
以上就是Tomcat加载Spring-Web模块时,SPI机制真的破坏了Java类加载器的可见性原则吗?的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号