暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

SPI机制

yuerer 2024-03-31
192

jdbc加载数据库驱动为例子

DriverManager.java中

static {
    loadInitialDrivers();
    println("JDBC DriverManager initialized");
}

    private static void loadInitialDrivers() {
        String drivers;
        try {      //加载系统变量
            drivers = AccessController.doPrivileged(new PrivilegedAction<String>() {
                public String run() {
                    return System.getProperty("jdbc.drivers");
                }
            });
        } catch (Exception ex) {
            drivers = null;
        }
        // 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()
        // SPI机制加载驱动类
        AccessController.doPrivileged(new PrivilegedAction<Void>() {
            public Void run() {
        //  通过ServiceLoader.load进行查找,我们的重点也是这里,后面分析
                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{                 // 遍历迭代器
                // 这里需要这么做,是因为ServiceLoader默认是延迟加载
                // 只是找到对应的class,但是不加载
                // 所以这里在调用next的时候,其实就是实例化了对应的对象了
                // 请注意这里 --------------------------------------------------------------------  1
                    while(driversIterator.hasNext()) {              // 真正实例化的逻辑,详见后面分析
                        driversIterator.next();
                    }
                } catch(Throwable t) {
                // Do nothing
                }
                return null;
            }
        });

        println("DriverManager.initialize: jdbc.drivers = " + drivers);

        if (drivers == null || drivers.equals("")) {
            return;
        }
        String[] driversList = drivers.split(":");
        println("number of Drivers:" + driversList.length);
        for (String aDriver : driversList) {
            try {
                println("DriverManager.Initialize: loading " + aDriver);        // 同时加载系统变量中找到的驱动类
                Class.forName(aDriver, true,
                        ClassLoader.getSystemClassLoader());
            } catch (Exception ex) {
                println("DriverManager.Initialize: load failed: " + ex);
            }
        }
    }


https://www.jianshu.com/p/3039aa89b1b5

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论