问题:Class.forName与ClassLoader区别?

ClassLoader仅会将.class文件加载到jvm中,并不会进行初始化(只有在程序使用时才会初始化【懒加载】)
Class.forName加载完成后,会执行类的静态代码块、为静态属性赋值。

理解:Class.forName(“com.mysql.jdbc.Driver”)

线程上下文类加载器(jdk1.2存在)
setContextClassLoader与getContextClassLoader用于获取和设置当前线程的上下文类加载器,如果当前线程没有设置上下文类加载,则和父线程保持一致。

为什么存在线程上下文类加载器?(父委托子)

因为jdk的双亲委派机制自身缺陷有关,jdk提供了很多SPI(Service Provider Interface)例如:JDBC、JCE、JNDI、JAXP、JBI等,JDK只是规定了这些接口之间的逻辑关系,没有提供具体实现。具体实现由第三方厂商提供。
image.png
Java使用JDBC这个SPI完全隔离应用和第三方驱动的具体实现,切换数据库,只需要替换第三方厂商驱动的具体实现。实现了应用程序面向接口编程,不用关心第三方具体实现。 但java.lang.sql中的所有接口都是有JDK提供,接口是有根加载器加载的第三方的驱动具体实现则需要使用系统类加载器加载 由于双亲委派机制的限制,根加载器不可能加载到第三方厂商提供的具体实现,为解决此问题,JDK采用了线程上下文类加载器,在此基础上,根加载器需要委托子类加载器加载厂商提供的SPI具体实现。 线程上下文类加载器,打破了父委托机制,父加载器委托子加载器,加载接口的具体实现。例如DBC、JCE、JNDI、JAXP、JBI等都这样实现。