1.线程上下文类加载器的需求场景是这样的,拿JDBC的driver加载来举例:
java.sql.DriverManager类是JDK的核心类,由BootClassLoader加载器来加载。
java.sql.DriverManager类里,加载具体实现类的源码:
private static void loadInitialDrivers() {
省略无关代码....
// If the driver is packaged as a Service Provider, load it.
// Get all the drivers through the classloader
// exposed as a java.sql.Driver.class service.
// ServiceLoader.load() replaces the sun.misc.Providers()
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
ServiceLoader<Driver> loadedDrivers = ServiceLoader.load(Driver.class);
Iterator<Driver> driversIterator = loadedDrivers.iterator();
省略无关代码....
可以看到,在java.sql.DriverManager类里需要加载具体实现类,但java.sql.DriverManager类是由BootClassLoader加载器加载的,所以这个时候就无法使用双亲委派模型来加载具体实现类了。
这时就只能使用SPI方式的线程上下文类加载器来加载具体实现类。
2.自己实现的框架,接口类和实现类一般都是由SystemClassLoader来加载的,这时候双亲委派模型可以正常使用。很多框架使用SPI方式的原因,不是因为双亲委派模型满足不了类加载需求,而是看重了SPI的易扩展性。