SPI和类加载器

主要目的

如果同时面临下面两个问题,就可以使用SPI
1)A模块依赖B模块。
2)A模块又要先于B模块被类加载。

大部分场景其实根本不需要SPI。合理的类依赖可以避免这个问题。

一个简单的demo

具体的例子见
https://blog.csdn.net/qq_27292113/article/details/100324127

核心代码如下

  • 在外部jar中定义services
    在这里插入图片描述
  • 使用是是会选择第一个实现
    在这里插入图片描述

类加载机制

实际应用

JDBC

DriverManager类会在其static代码段执行

                ServiceLoader<Driver> loadedDrivers = ServiceLoader.load(Driver.class);
                Iterator<Driver> driversIterator = loadedDrivers.iterator();

                /* Load these drivers, so that they can be instantiated.
                 * It may be the case that the driver class may not be there
                 * i.e. there may be a packaged driver with the service class
                 * as implementation of java.sql.Driver but the actual class
                 * may be missing. In that case a java.util.ServiceConfigurationError
                 * will be thrown at runtime by the VM trying to locate
                 * and load the service.
                 *
                 * Adding a try catch block to catch those runtime errors
                 * if driver not available in classpath but it's
                 * packaged as service and that service is there in classpath.
                 */
                try{
                    while(driversIterator.hasNext()) {
                        driversIterator.next();
                    }
                } catch(Throwable t) {
                // Do nothing
                }
                return null;

注释上写的很清楚

driver接口定义了如下方法
在这里插入图片描述
可以看到有诸多的实现。
在这里插入图片描述
简单而言,就是自动加载:DriverManager的静态代码块执行的时刻,使用该时刻当前线程类加载器加载java.sql.Driver文件,并用当前线程类加载器加载及、实例化、registerDriver

猜你喜欢

转载自blog.csdn.net/define_us/article/details/110482191