- blogs:
- cles::blog

JDBC はいつから Class.forName() が必要なくなったのか

昨日書いた JDBC から MySQL への接続プログラムを読み返していて、Class.forName() を使っていないことに気づきました。少し前までは Class.forName() しないと java.lang.NoClassDefFoundError が発生していたはずなので、いつから仕様が変わっていたんだろうと思って改めて調べてみたら JDBC 4.0 ( JavaSE 6 ) からのようでした*1。JDBC 4.0 自体の新機能は Java6 を使い始めたときに調べていたはずなのですが、この部分だけ読み落としていたようです。
† DriverManager のリファレンスを調べてみる
確かに JavaSE 6 の java.sql.DriverManager には下記のような記述がありますね。
DriverManager (Java Platform SE 6)
DriverManager メソッド getConnection と getDrivers は、Java Standard Edition サービスプロバイダメカニズムをサポートするように拡張されました。JDBC 4.0 ドライバは、ファイル META-INF/services/java.sql.Driver を含める必要があります。このファイルには、java.sql.Driver の JDBC ドライバ実装の名前が含まれます。たとえば my.sql.Driver クラスをロードするために、META-INF/services/java.sql.Driver ファイルに次のエントリが含まれます。
このドキュメントのサービスプロバイダをたどってみると、下記のような記述がありました。
JAR ファイルの仕様
META-INF/services ディレクトリ内のファイルは、サービスプロバイダの構成ファイルです。サービスとは、よく使われるインタフェースとクラス (通常は abstract) のセットのことです。サービスプロバイダとは、サービスの特定の実装のことです。通常、プロバイダのクラスによって、サービス自体に定義されているクラスのインタフェースとサブクラスが実装されます。サービスプロバイダを Java プラットフォームの実装にインストールするときは、拡張機能の形式、つまり、拡張機能の通常のディレクトリに配置される jar ファイルの形式で行われます。プロバイダを利用可能にするには、アプレットまたはアプリケーションのクラスパスに追加するか、プラットフォーム固有の方法を使います。
というわけで、今回接続に使った mysql-connector-java-5.1.22-bin.jar を解凍してみると、サービスプロバイダ用のファイルがちゃんと入っていました。
\META-INF\services\java.sql.Driver
† これは JDBC だけでなく汎用的な仕掛けだった
これがどのようなメカニズムでロードされるのか調べてみたところ、 java.util.ServiceLoader<S>*2 というクラスを使えば、JDBC ドライバ以外のクラスもこんな感じで自由にロードできるようですね。
ServiceLoader (Java Platform SE 6)
このプログラム中の CodecSet.class は Interface、ServiceLoader は Iterable<S> なので、拡張 for 文などを使えばインスタンスが取り出せるようです。
これが何で Iterable<S> なのかと思ったら複数クラスを登録することができる*3からなんですね。いろいろと勉強になりました。
- *1: JDBCドライバーメモ(Hishidama's Java DriverManager Memo)
- *2: ServiceLoader (Java Platform SE 6)
- *3: Java技術最前線 - 「Java SE 6完全攻略」第11回 コンポーネントのロードを行うServiceLoader:ITpro
このエントリへのTrackbackにはこのURLが必要です→https://blog.cles.jp/item/5352
古いエントリについてはコメント制御しているため、即時に反映されないことがあります。
コメントは承認後の表示となります。
OpenIDでログインすると、即時に公開されます。
OpenID を使ってログインすることができます。
2 . Word で数式がグレーアウトされていて挿入できないときは(6758)
3 . Windows 10 で勝手にログアウトされないようにする(5161)
4 . Firefox でパスワードが保存されるページとされないページの違い(3909)
5 . awk で指定した n カラム目以降を出力する(3485)