Class.forName()は何をしましたか?

12198 ワード

JDBC接続には、一般的に次の手順が必要です.1ドライバのロード
Class.forName("com.mysql.jdbc.Driver");

2接続オブジェクトの取得
Connection con=
    DriverManager.getConnection("jdbc:mysql://localhost:3306/homeworksubmit?user=root&password=root&useUnicode=true&characterEncoding=UTF-8");

3コマンド・オブジェクトの作成
Statement stmt =
     con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
                                       ResultSet.CONCUR_READ_ONLY);

4 sql文の実行
Result rs=stmt.executeQuery(sql);

しかし疑問なのは第一歩で、対像を返さず、ソースコードを追跡した.
Returns the {@code Class} object associated with the class or
interface with the given string name.
equivalent to:
{@code Class.forName(className, true, currentLoader)}

次のステップで取得するオブジェクトは、通常、次のステップの呼び出しを容易にするため、Class.forName()がどのように実行されているのか、どのような仕事をしているのか、それを知ってこそ、JDBC接続の理解が深まります.ここではまずDriverクラスのソースコードを貼ります.
* The Java SQL framework allows for multiple database drivers. Each driver
 * should supply a class that implements the Driver interface
 * 
 * <p>
 * The DriverManager will try to load as many drivers as it can find and then
 * for any given connection request, it will ask each driver in turn to try to
 * connect to the target URL.
 * 
 * <p>
 * It is strongly recommended that each Driver class should be small and
 * standalone so that the Driver class can be loaded and queried without
 * bringing in vast quantities of supporting code.
 * 
 * <p>
 * When a Driver class is loaded, it should create an instance of itself and
 * register it with the DriverManager. This means that a user can load and
 * register a driver by doing Class.forName("foo.bah.Driver")

ドライバクラスごとにDriverインタフェースを実装する必要があります.ドライバがロードされると、まずオブジェクトをインスタンス化し、DriverManagerに登録します.com.mysql.jdbc.Driverのコードの一部:
Driverクラスを初期化すると、その中の静的コードも実行され、次の文が自動的に実行されます.
java.sql.DriverManager.registerDriver(new Driver());
public class Driver extends NonRegisteringDriver implements java.sql.Driver {
    // ~ Static fields/initializers
    // ---------------------------------------------

    //
    // Register ourselves with the DriverManager
    //
    static {
        try {
            java.sql.DriverManager.registerDriver(new Driver());
        } catch (SQLException E) {
            throw new RuntimeException("Can't register driver!");
        }
    }

    ……
}

このようにforName()を使用してDriverを初期化すると、MySqlドライバが自動的にDriverManagementクラスに登録され、DriverManagerでMysqLへの接続が得られます.registerDriver()ソースコードの解釈を貼り付けます.
* Registers the given driver with the <code>DriverManager</code>.

実装コードの一部:
public static synchronized void registerDriver(java.sql.Driver driver)
        throws SQLException {

        /* Register the driver if it has not already been added to our list */
        if(driver != null) {
            registeredDrivers.addIfAbsent(new DriverInfo(driver));
        } else {
            // This is for compatibility with the original DriverManager
            throw new NullPointerException();
        }

        println("registerDriver: " + driver);

    }

新DriverInfo(driver)では、次にDriverInfo(driver)クラスを見てみましょう.DriverInfoは非常に簡単で、Driverの情報を保存するのに使用されます.3つのメンバー変数しかありません.Driver、DriverClass、DriverClassNameは、非常に意味があります.
クラスがメモリにロードされると、クラス内の静的初期化プロセスが実行され、ドライバの登録プロセスが完了します.次にデータベース接続を確立するコードを重点的に見て、getConnection関数では、
/**
     * Attempts to establish a connection to the given database URL.
     * The <code>DriverManager</code> attempts to select an appropriate driver from
     * the set of registered JDBC drivers.
     *
     * @param url a database url of the form
     *  <code> jdbc:<em>subprotocol</em>:<em>subname</em></code>
     * @return a connection to the URL
     * @exception SQLException if a database access error occurs
     */

実装関数:
 @CallerSensitive
    public static Connection getConnection(String url)
        throws SQLException {

        java.util.Properties info = new java.util.Properties();
        return (getConnection(url, info, Reflection.getCallerClass()));
    }

ここまででほぼ接続が完了しました.次に、ソースコードで登録されたJDBCドライバから適切なドライバを試してみると、ポーリング方式で、登録されたドライバが多くなると接続速度が遅くなります.JDBCがデータベースに接続する速度が遅いのは、このような実現方法と関係があるのではないでしょうか.Driverクラスを見てみましょう.
public class Driver extends NonRegisteringDriver implements java.sql.Driver

NonRegisteringDriverの実装を見てみましょう.
public java.sql.Connection connect(String url, Properties info)
            throws SQLException {
        if (url != null) {
            if (StringUtils.startsWithIgnoreCase(url, LOADBALANCE_URL_PREFIX)) {
                return connectLoadBalanced(url, info);
            } else if (StringUtils.startsWithIgnoreCase(url,
                    REPLICATION_URL_PREFIX)) {
                return connectReplicationConnection(url, info);
            }
        }

        Properties props = null;

        if ((props = parseURL(url, info)) == null) {
            return null;
        }

        try {
            Connection newConn = new com.mysql.jdbc.Connection(host(props),
                    port(props), props, database(props), url);

            return newConn;
        } catch (SQLException sqlEx) {
            // Don't wrap SQLExceptions, throw
            // them un-changed.
            throw sqlEx;
        } catch (Exception ex) {
            throw SQLError.createSQLException(Messages
                    .getString("NonRegisteringDriver.17") //$NON-NLS-1$
                    + ex.toString()
                    + Messages.getString("NonRegisteringDriver.18"), //$NON-NLS-1$
                    SQLError.SQL_STATE_UNABLE_TO_CONNECT_TO_DATASOURCE);
        }
    }

まずparseURLを使用し、Connectionを使用して接続を確立します.parseURLは単純な文字列解析にすぎず、主に入力された接続文字列が「jdbc:mysql://host:port/database「の形式で、満たされていない場合はnullに戻り、次のDriverをDriverManagerでテストします.満たされている場合はConnectionオブジェクトを作成して実際のデータベース接続を確立します.先ほどの質問の答えは、DriverManagerのポーリングクエリによって登録されたDriverオブジェクトの動作に伴うパフォーマンスのコストはそれほど大きくありません.主なワークロードはparseだけですURL関数.
ソースコードはここまで遡って終わり、残りは管理しません.