dubboSPI和jdkSPI的區別
阿新 • • 發佈:2022-03-16
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。