JDBC破坏双亲委派机制

未破坏双亲委派机制的情况

原先链接数据的代码:

String url = "jdbc:mysql://localhost:3306";
String username = "root";
String password = "root";

// 注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
// 获取连接
Connection connection = DriverManager.getConnection(url, username, password);

Class.forName() 触发加载MySQL驱动,上述过程并没有破坏双亲委派机制,使用的类加载器和 调用类的加载器一样( ApplicationClassLoader)。

破坏双亲委派机制的情况

在JDBC 4.0之后使用spi机制,我们不再需要调用Class.forName()方法去加载驱动类。只需要将对应的驱动类jar包放到工程的class path下,驱动类会自动被加载。

String url = "jdbc:mysql://localhost:3306";
String username = "root";
String password = "root";

// 注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
// 获取连接
Connection connection = DriverManager.getConnection(url, username, password);

DriverManager的类加载问题

类加载的范围受到限制,某些情况下父class loader无法加载某些类文件,这时候就需要委托到下层级的class loader去加载类文件。

JDBC的driver接口定义在JDK中,但是它的实现类是放在classpath下的(比如MySQL)。

  • DriverManager类会加载每个Driver接口的实现类并管理它们,但是DriverManager类自身是 jre/lib/rt.jar 里的类,是由bootstrap classloader加载的
  • 根据类加载机制,某个类需要引用其它类的时候,虚拟机将会用这个类的classloader去加载被引用的类
  • boostrap classloader显然是无法加载到MySQL driver的(ClassNotFoundException)
  • 因此只能在DriverManager里强行指定下层classloader来加载Driver实现类,而这就会打破双亲委派模型

java开发者的设计是,添加一个线程上下文类加载器(Thread Context ClassLoader),在启动类加载器中获取应用程序类加载器。 Thread.setContextClassLoaser() 设置线程上下文类加载器,如果创建线程的时候没有设置,会从父类继承一个,默认应用程序类加载器。

线程上下文类加载器是让父类加载器请求子类加载器完成类的加载,打破了双亲委派机制。

© 版权声明
THE END
请撒泡尿证明你到此一游
点赞0 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容