V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
Newyorkcity
V2EX  ›  问与答

Java 关于 Class.forName(com.mysql.jdbc.Driver) 未遵守了双亲委派模型这件事有什么比较好资料么?

  •  
  •   Newyorkcity · 2020-05-10 17:37:08 +08:00 · 1280 次点击
    这是一个创建于 1664 天前的主题,其中的信息可能已经有所发展或是发生改变。
    为什么必须要破坏?

    如何破坏的?

    谢谢
    2 条回复    2020-05-11 11:43:26 +08:00
    sawyera
        1
    sawyera  
       2020-05-10 21:46:05 +08:00   ❤️ 1
    先说结论:Class.forName 遵循双亲委派机制

    参考:
    Class.forName 方法:
    @CallerSensitive
    public static Class<?> forName(String className)
    throws ClassNotFoundException {
    Class<?> caller = Reflection.getCallerClass();
    return forName0(className, true, ClassLoader.getClassLoader(caller), caller);
    }

    可以看出是使用 ClassLoader.getClassLoader(caller) 类加载器进行加载的,默认是使用的用户类加载器,还是符合双亲委派机制的。

    如有错误,请指出
    isir1234
        2
    isir1234  
       2020-05-11 11:43:26 +08:00   ❤️ 1
    为什么必须要破坏?::
    DriverManager::getConnection 方法需要根据参数传进来的 url 从所有已经加载过的 Drivers 里找到一个合适的 Driver 实现类去连接数据库.
    Driver 实现类在第三方 jar 里, 要用 AppClassLoader 加载. 而 DriverManager 是 rt.jar 里的类, 被 BootstrapClassLoader 加载, DriverManager 没法用 BootstrapClassLoader 去加载 Driver 实现类, 所以只能破坏双亲委派模型, 用它下级的 AppClassLoader 去加载 Driver.

    如何破坏的?::
    > SPI 机制
    Driver 具体的实现类 jar 包在 META-INF/services/java.sql.Driver 文件里写上自己 Driver 实现类的全限定名, 比如 `org.postgresql.Driver` , JDK8 的 DriverManager 在 static 代码块里(JDK14 是在第一次 getConnection 时)会用 ServiceLoader 获取所有的 Driver 并使用 Thread.currentThread().getContextClassLoader() 获取到的 AppClassLoader 加载该类, Driver 实现类的 static 代码块会去调用 DriverManager::registerDriver 将自己注册到 DriverManager 里.

    个人理解...
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2940 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 34ms · UTC 02:45 · PVG 10:45 · LAX 18:45 · JFK 21:45
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.