5.3. サービス依存関係の種類
サービスは、以下の方法のいずれかを使用して他のサービスの依存関係を宣言できます。
- @org.hibernate.service.spi.InjectService
単一のパラメーターを受け入れ、
@InjectService
でアノテーションが付けられたサービス実装クラスのメソッドは 、別のサービスの挿入を要求していると見なされます。デフォルトでは、method パラメーターのタイプは、インジェクトされるサービ出力ルになることが想定されます。パラメーターのタイプがサービ出力ルと異なる場合は、
InjectService
のserviceRole
属性を使用してロールに明示的な名前を付ける必要があります。デフォルトでは、インジェクトされたサービスは必須とみなされ、名前付き依存サービスがないと、起動に失敗します。インジェクトされるサービスがオプションの場合、
InjectService
の必要な属性はfalse
として宣言される必要があります。デフォルトはtrue
です。- org.hibernate.service.spi.ServiceRegistryAwareService
次のアプローチは、単一の
injectServices
メソッドを宣言する、オプションのサービスインターフェイスorg.hibernate.service.spi.ServiceRegistryAwareService
をサービスが実装するプルアプローチです。Hibernate は起動時に、
org.hibernate.service.ServiceRegistry
自体をこのインターフェイスを実装するサービスに挿入します。その後、ServiceRegistry
参照を使用して必要な追加サービスを見つけることができます。
5.3.1. サービスレジストリー
5.3.1.1. ServiceRegistry について
中央のサービス API はサービス自体以外に、org.hibernate.service.ServiceRegistry インターフェイスです。サービスレジストリーの主な目的は、サービスへのアクセスを保持し、管理し、提供することです。
サービスレジストリーは階層的です。あるレジストリーのサービスは、同じレジストリーのサービスや任意の親レジストリーに依存して使用できます。
org.hibernate.service.ServiceRegistryBuilder を使用して org.hibernate.service.ServiceRegistry インスタンスをビルドします。
ServiceRegistryBuilder を使用した ServiceRegistry の作成例
ServiceRegistryBuilder registryBuilder = new ServiceRegistryBuilder( bootstrapServiceRegistry ); ServiceRegistry serviceRegistry = registryBuilder.buildServiceRegistry();
5.3.2. カスタムサービス
5.3.2.1. カスタムサービスについて
org.hibernate.service.ServiceRegistry
を構築すると、不変とみなされます。このサービス自体は再設定を受け入れる可能性がありますが、ここでの不変性はサービスの追加または置き換えを意味します。そのため、org.hibernate.service.ServiceRegistryBuilder
で利用できる別のロールは、これから生成される org.hibernate.service.ServiceRegistry
に含まれるサービスの調整を許可することです。
カスタムサービスについて org.hibernate.service.ServiceRegistryBuilder
に指示する方法は 2 つあります。
-
org.hibernate.service.spi.BasicServiceInitiator
クラスを実装し、サービスクラスのオンデマンド構築を制御し、addInitiator
メソッドを使用してorg.hibernate.service.ServiceRegistryBuilder
に追加します。 -
サービスクラスをインスタンス化し、
addService
メソッドを使用して、org.hibernate.service.ServiceRegistryBuilder
に追加します。
新規サービ出力ルの追加やサービス実装の置き換えなどサービスの上書きなど、レジストリーの拡張にはいずれかのアプローチが有効です。
例: ServiceRegistryBuilder を使用して、既存のサービスをカスタムサービスに置き換える
ServiceRegistryBuilder registryBuilder = new ServiceRegistryBuilder(bootstrapServiceRegistry); registryBuilder.addService(JdbcServices.class, new MyCustomJdbcService()); ServiceRegistry serviceRegistry = registryBuilder.buildServiceRegistry(); public class MyCustomJdbcService implements JdbcServices{ @Override public ConnectionProvider getConnectionProvider() { return null; } @Override public Dialect getDialect() { return null; } @Override public SqlStatementLogger getSqlStatementLogger() { return null; } @Override public SqlExceptionHelper getSqlExceptionHelper() { return null; } @Override public ExtractedDatabaseMetaData getExtractedMetaDataSupport() { return null; } @Override public LobCreator getLobCreator(LobCreationContext lobCreationContext) { return null; } @Override public ResultSetWrapper getResultSetWrapper() { return null; } }
5.3.3. Boot-Strap レジストリー
5.3.3.1. Boot-strap レジストリーについて
boot-strap レジストリーは、ほとんどの機能を機能させるために絶対に利用できるようにする必要のあるサービスを保持します。ここでの主要なサービスは、ClassLoaderService
です。これは最適な例です。設定ファイルを解決する場合でも、クラスローディングサービス (例: リソース検索) へのアクセスが必要になります。これは、通常の使用時に親ではなく、ルートレジストリーです。
boot-strap レジストリーのインスタンスは、org.hibernate.service.BootstrapServiceRegistryBuilder
クラスを使用して作成されます。
BootstrapServiceRegistryBuilder の使用
例: BootstrapServiceRegistryBuilder の使用
BootstrapServiceRegistry bootstrapServiceRegistry = new BootstrapServiceRegistryBuilder() // pass in org.hibernate.integrator.spi.Integrator instances which are not // auto-discovered (for whatever reason) but which should be included .with(anExplicitIntegrator) // pass in a class loader that Hibernate should use to load application classes .with(anExplicitClassLoaderForApplicationClasses) // pass in a class loader that Hibernate should use to load resources .with(anExplicitClassLoaderForResources) // see BootstrapServiceRegistryBuilder for rest of available methods ... // finally, build the bootstrap registry with all the above options .build();
5.3.3.2. BootstrapRegistry サービス
org.hibernate.service.classloading.spi.ClassLoaderService
Hibernate はクラスローダーと対話する必要があります。ただし、Hibernate または任意のライブラリーと対話する方法は、アプリケーションをホストしているランタイム環境によって異なります。アプリケーションサーバー、OSGi コンテナー、およびその他のモジュラークラスローディングシステムでは、非常に特殊なクラスローディング要件が課せられています。このサービスは、この環境的な複雑性からの抽象化を Hibernate に提供します。また、同様に重要な点として、単一スワップ可能なコンポーネントでこれを実行します。
クラスローダーとの対話では、Hibernate には以下の機能が必要になります。
- アプリケーションクラスを検索する機能
- インテグレーションクラスを検索する機能
- プロパティーファイルや XML ファイルなどのリソースを検索する機能
java.util.ServiceLoader
をロードする機能注記現在、アプリケーションクラスをロードする機能と、統合クラスをロードする機能が、サービス上の単一の load class 機能に統合されています。これは、今後のリリースで変更される可能性があります。
org.hibernate.integrator.spi.IntegratorService
アプリケーション、アドオン、およびその他のモジュールは Hibernate と統合する必要があります。前述の方法では、各モジュールの登録を調整するために、通常アプリケーションなどのコンポーネントが必要でした。この登録は、各モジュールのインテグレーターに代わって実施されました。
このサービスは、検出機能に重点を置いています。
org.hibernate.integrator.spi.Integrator
のコントラクトの実装を検出するために、org.hibernate.service.classloading.spi.ClassLoaderService
が提供する標準の Javajava.util.ServiceLoader
機能を利用します。インテグレーターは、単に
/META-INF/services/org.hibernate.integrator.spi.Integrator
という名前のファイルを定義し、これをクラスパスで利用できるようにします。このファイルは、
java.util.ServiceLoader
メカニズムによって使用されます。これは、1 行ずつorg.hibernate.integrator.spi.Integrator
インターフェイスを実装するクラスの完全修飾名を一覧表示します。
5.3.4. SessionFactory レジストリー
すべてのレジストリータイプのインスタンスを指定の org.hibernate.SessionFactory
のターゲットとして扱うのがベストプラクティスですが、このグループのサービスのインスタンスは単一の org.hibernate.SessionFactory
に明示的に所属します。
相違点は、開始タイミングに関する事項です。通常、org.hibernate.SessionFactory
にアクセスするにはアクセスが必要になります。この特別なレジストリーは org.hibernate.service.spi.SessionFactoryServiceRegistry
です。
5.3.4.1. SessionFactory サービス
org.hibernate.event.service.spi.EventListenerRegistry
- 説明
- イベントリスナーを管理するためのサービスです。
- イニシエーター
-
org.hibernate.event.service.internal.EventListenerServiceInitiator
- 実装
-
org.hibernate.event.service.internal.EventListenerRegistryImpl
5.3.5. インテグレーター
org.hibernate.integrator.spi.Integrator
は、開発者が機能している SessionFactory
をビルドするプロセスにフックできるようにする簡単な方法を提供することを目的としています。org.hibernate.integrator.spi.Integrator
インターフェイスは関連する以下のメソッドを定義します。
-
integrate
では、ビルドプロセスへのフックが可能になります。 -
disintegrate
では、SessionFactory
をシャットダウンできます。
統合のオーバーロード形式である org.hibernate.integrator.spi.Integrator
で定義されている 3 つ目のメソッドがあります。これは、org.hibernate.cfg.Configuration
ではなく、org.hibernate.metamodel.source.MetadataImplementor
を受け入れます。
IntegratorService
で利用できる検出アプローチに加え、BootstrapServiceRegistry
のビルド時にアプリケーションが手動でインテグレーター実装を登録できます。
5.3.5.1. インテグレーターのユースケース
org.hibernate.integrator.spi.Integrator
の主なユースケースは、イベントリスナーを登録し、サービスを提供します。org.hibernate.integrator.spi.ServiceContributingIntegrator
を参照してください。
例: イベントリスナーの登録
public class MyIntegrator implements org.hibernate.integrator.spi.Integrator { public void integrate( Configuration configuration, SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) { // As you might expect, an EventListenerRegistry is the thing with which event listeners are registered It is a // service so we look it up using the service registry final EventListenerRegistry eventListenerRegistry = serviceRegistry.getService(EventListenerRegistry.class); // If you wish to have custom determination and handling of "duplicate" listeners, you would have to add an // implementation of the org.hibernate.event.service.spi.DuplicationStrategy contract like this eventListenerRegistry.addDuplicationStrategy(myDuplicationStrategy); // EventListenerRegistry defines 3 ways to register listeners: // 1) This form overrides any existing registrations with eventListenerRegistry.setListeners(EventType.AUTO_FLUSH, myCompleteSetOfListeners); // 2) This form adds the specified listener(s) to the beginning of the listener chain eventListenerRegistry.prependListeners(EventType.AUTO_FLUSH, myListenersToBeCalledFirst); // 3) This form adds the specified listener(s) to the end of the listener chain eventListenerRegistry.appendListeners(EventType.AUTO_FLUSH, myListenersToBeCalledLast); } }