JDBCが実現するサービスプロバイダフレームワーク

19283 ワード

1.フレームワークの紹介
サービスプロバイダフレームワークとは、複数のサービスプロバイダが1つのサービスを実現し、システムがサービスプロバイダのカスタマーサービス側に複数の実装を提供し、それらを複数の実装からデカップリングするシステムを指す.サービスフレームワークには、次の4つのコンポーネントがあります.
  • サービスインタフェース:プロバイダが実装するための
  • プロバイダ登録API:システムは登録実装に使用され、カスタマーサービス側に
  • にアクセスさせる.
  • サービスアクセスAPI:クライアントがサービスを取得するために使用するインスタンス
  • サービスプロバイダインタフェース(オプション):サービスインプリメンテーションの作成を担当するインスタンス
  • .
    2.JDBCの実現
    JDBC接続データベースの重要な2つのステップは、ドライバのロードと接続の取得です.
    1.ドライバをロードし、ドライバの静的コードブロックを実行することで、DiverManagerに登録します.
     #    
     Class.forName("com.mysql.cj.jdbc.Driver");
    
    private final static CopyOnWriteArrayList<DriverInfo> registeredDrivers = new CopyOnWriteArrayList<>();
    #  mysql     ,    
    public class Driver extends NonRegisteringDriver implements java.sql.Driver {
        public Driver() throws SQLException {
        }
    
        static {
            try {
            #      
                DriverManager.registerDriver(new Driver());
            } catch (SQLException var1) {
                throw new RuntimeException("Can't register driver!");
            }
        }
    }
    
     public static synchronized void registerDriver(java.sql.Driver driver)
          throws SQLException {
    
          registerDriver(driver, null);
      }
     public static synchronized void registerDriver(java.sql.Driver driver,
              DriverAction da)
          throws SQLException {
          //      ,        
          if(driver != null) {
              registeredDrivers.addIfAbsent(new DriverInfo(driver, da));
          } else {
              throw new NullPointerException();
          }
          println("registerDriver: " + driver);
      }
    

    2.接続を取得し、登録されたドライバを見つけ、ドライバ実装のconnectメソッドを呼び出す
     Connection conn=DriverManager.getConnection(url, user, password);
     
     public static Connection getConnection(String url,
            String user, String password) throws SQLException {
            java.util.Properties info = new java.util.Properties();
    
            if (user != null) {
                info.put("user", user);
            }
            if (password != null) {
                info.put("password", password);
            }
    
            return (getConnection(url, info, Reflection.getCallerClass()));
        }
        
    private static Connection getConnection(
            String url, java.util.Properties info, Class<?> caller) throws SQLException {
            /*
             * When callerCl is null, we should check the application's
             * (which is invoking this class indirectly)
             * classloader, so that the JDBC driver class outside rt.jar
             * can be loaded from here.
             */
            ClassLoader callerCL = caller != null ? caller.getClassLoader() : null;
            synchronized(DriverManager.class) {
                // synchronize loading of the correct classloader.
                if (callerCL == null) {
                    callerCL = Thread.currentThread().getContextClassLoader();
                }
            }
    
            if(url == null) {
                throw new SQLException("The url cannot be null", "08001");
            }
    
            println("DriverManager.getConnection(\"" + url + "\")");
    
            // Walk through the loaded registeredDrivers attempting to make a connection.
            // Remember the first exception that gets raised so we can reraise it.
            SQLException reason = null;
    
            for(DriverInfo aDriver : registeredDrivers) {
                // If the caller does not have permission to load the driver then
                // skip it.
                if(isDriverAllowed(aDriver.driver, callerCL)) {
                    try {
                        println("    trying " + aDriver.driver.getClass().getName());
                        Connection con = aDriver.driver.connect(url, info);
                        if (con != null) {
                            // Success!
                            println("getConnection returning " + aDriver.driver.getClass().getName());
                            return (con);
                        }
                    } catch (SQLException ex) {
                        if (reason == null) {
                            reason = ex;
                        }
                    }
    
                } else {
                    println("    skipping: " + aDriver.getClass().getName());
                }
    
            }
    
            // if we got here nobody could connect.
            if (reason != null)    {
                println("getConnection failed: " + reason);
                throw reason;
            }
    
            println("getConnection: no suitable driver found for "+ url);
            throw new SQLException("No suitable driver found for "+ url, "08001");
        }
    

    JDBCにとってConnectionはサービスインタフェースであり、DriverManagement.registerDriverプロバイダ登録API,DriverManager.getConnectionはサービスアクセスAPIであり、Driverはサービスプロバイダインタフェースである.