5.3. サービス依存関係の種類

サービスは、以下の方法のいずれかを使用して他のサービスの依存関係を宣言できます。

@org.hibernate.service.spi.InjectService

単一のパラメーターを受け入れ、@InjectService でアノテーションが付けられたサービス実装クラスのメソッドは 、別のサービスの挿入を要求していると見なされます。

デフォルトでは、method パラメーターのタイプは、インジェクトされるサービ出力ルになることが想定されます。パラメーターのタイプがサービ出力ルと異なる場合は、InjectServiceserviceRole 属性を使用してロールに明示的な名前を付ける必要があります。

デフォルトでは、インジェクトされたサービスは必須とみなされ、名前付き依存サービスがないと、起動に失敗します。インジェクトされるサービスがオプションの場合、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 が提供する標準の Java java.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);
    }
}