1. 程式人生 > 其它 >dubboSPI和jdkSPI的區別

dubboSPI和jdkSPI的區別

dubboSPI和jdkSPI的區別

什麼是SPI

SPI(Service Provider Interface)。Java在語言層面為我們提供了一種方便地建立可擴充套件應用的途徑。SPI提供了一種JVM級別的服務發現機制,我們只需要按照SPI的要求,在jar包中進行適當的配置,jvm就會在執行時通過懶載入,幫我們找到所需的服務並載入。如果我們一直不使用某個服務,那麼它不會被載入,一定程度上避免了資源的浪費。

JDK SPI最常見的例子就是java.sql.DriverManager中載入sql驅動的例子。

Java SPI

JDK自帶的SPI的類是:java.util.ServiceLoader
使用方法以JDBC為例:

        // java.sql.DriverManager 首先在靜態程式碼塊中初始化全部懶載入進來
        // 首先拿到迭代器,而這個迭代器中,其實是拿一個掃描一個provider的 懶載入
        ServiceLoader<Driver> loadedDrivers = ServiceLoader.load(Driver.class);
        Iterator<Driver> driversIterator = loadedDrivers.iterator();
        // 以上程式碼還沒有例項化過任何 Driver provider,以下程式碼,DriverManager才開始自動載入
        try {
            while (driversIterator.hasNext()) {
                driversIterator.next();
            }
        } catch (Throwable t) {
            // Do nothing
        }
        return null;

懶載入如下圖所示,在load()了ServiceLoader後,經過引數檢查 直接開始清空provider的快取,然後重新獲取provider。先查詢已經快取的provider有沒有,如果沒有再去遍歷拿到新的provider。

而在載入過上述Driver provider之後,就會執行他的靜態程式碼塊,以DruidDriver為例具體程式碼如下所示:

    static {
        AccessController.doPrivileged(new PrivilegedAction<Object>() {
            public Object run() {
                DruidDriver.registerDriver(DruidDriver.instance);
                return null;
            }
        });
    }

 public static boolean registerDriver(Driver driver) {
        try {
            DriverManager.registerDriver(driver);

            try {
                MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();
                ObjectName objectName = new ObjectName("com.alibaba.druid:type=DruidDriver");
                if (!mbeanServer.isRegistered(objectName)) {
                    mbeanServer.registerMBean(instance, objectName);
                }
            } catch (Throwable var3) {
                if (LOG == null) {
                    LOG = LogFactory.getLog(DruidDriver.class);
                }

                LOG.error("register druid-driver mbean error", var3);
            }

            return true;
        } catch (Exception var4) {
            if (LOG == null) {
                LOG = LogFactory.getLog(DruidDriver.class);
            }

            LOG.error("registerDriver error", var4);
            return false;
        }
    }

他相當於把 自己例項化後,又交給了DriverManager控制。
以上就是 jdk自帶的SPI。

Dubbo SPI

對比和總結