Locked History Actions

Diff for "guice/Manual/Integration/CustomInjections"

Differences between revisions 2 and 3
Deletions are marked like this. Additions are marked like this.
Line 8: Line 8:
TypeListeners get notified of the types that Guice injects. Since type listeners are only notified once-per-type, they are the best place to run potentially slow operations, such as enumerating a type's members. With their inspection complete, type listeners may register instance listeners for values as they're injected. Guiceが注入を行うとき、TypeListenerはその型を通知される。
一つの型について一度だけ通知されるので、その型のメンバーを列挙するなどの特に多い操作を行うのにもっとも適切である。
With their inspection complete, type listeners may register instance listeners for values as they're injected.
Line 10: Line 12:
MembersInjectors and InjectionListeners can be used to receive a callback after Guice has injected an instance. The instance is first injected by Guice, then by the custom members injectors, and finally the injection listeners are notified. Since they're notified once-per-instance, these should execute as quickly as possible.
Example: Injecting a Log4J Logger
MembersInjectorsとInjectionListenersはGuiceがインスタンスへの注入を行った後でコールバックを受け取ることに使用できる。
インスタンスは最初にGuiceの注入を受け、次にカスタムメンバーインジェクタによる注入を受け、最後にインジェクションリスナに通知される。
それらはインスタンスごとに通知されるため、その実行はできるだけ素早く行う必要がある。
Line 13: Line 16:
Guice includes built-in support for injecting java.util.Logger instances that are named using the type of the injected instance. With the type listener API, you can inject a org.apache.log4j.Logger with the same high-fidelity naming. We'll be injecting fields of this format: 例:Log4Jロガーに注入する

Guiceはjava.util.Loggerインスタンスに注入するビルトインサポートがあり、それらは注入を受けるインスタンスの型の名称が使われる。
タイプリスナAPIを使うことによりorg.apache.log4j.Loggerに対して同様のhigh-fidelityネーミングを行うことができる。
このフォーマットのフィールドに注入してみよう。
Line 24: Line 31:
We start by registering our custom type listener Log4JTypeListener in a module. We use a matcher to select which types we listen for: モジュールにてカスタムタイプリスナLog4JTypeListenerをまず登録する。
matcherを使って、どのタイプをリッスンするかを選択する。
Line 30: Line 38:
You can implement the TypeListener to scan through a type's fields, looking for Log4J loggers. For each logger field that's encountered, we register a Log4JMembersInjector on the passed-in TypeEncounter: TypeListenerにて型のフィールドをスキャンして、Log4Jロガーを探す。
見つかったロガーフィールドそれぞれについて渡されたTypeEncounterにLog4JMembersInjectorを登録する。
Line 43: Line 52:
Finally, we implement the Log4JMembersInjector to set the logger. In this examle, we always set the field to the same instance. In your application you may need to compute a value or request one from a provider. 最後にLog4JMembersInjectorをロガーをセットするように実装する。
この例では、フィールドに同じインスタンスをセットするようにしている。
実際のアプリケーションでは、値を導出するか、プロバイダにリクエストするようにする。

カスタムインジェクション

標準的な@Injectによる注入のほか、Guiceはカスタム注入のためのフックを提供している。 これにより、それ自身のセマンティックスやアノテーションを持つ他のフレームワークのホストをGuiceとすることができる。 多くの開発者は直接的にカスタム注入を使うことはないだろうが、(訳注:Guiceの?)エクステンションやサードパーティライブラリでこれらを目にすることがあるかもしれない。 それぞれのカスタム注入についてはそれぞれタイプリスナ、インジェクションリスナと登録が必要である。

Guiceが注入を行うとき、TypeListenerはその型を通知される。 一つの型について一度だけ通知されるので、その型のメンバーを列挙するなどの特に多い操作を行うのにもっとも適切である。 With their inspection complete, type listeners may register instance listeners for values as they're injected.

MembersInjectorsInjectionListenersはGuiceがインスタンスへの注入を行った後でコールバックを受け取ることに使用できる。 インスタンスは最初にGuiceの注入を受け、次にカスタムメンバーインジェクタによる注入を受け、最後にインジェクションリスナに通知される。 それらはインスタンスごとに通知されるため、その実行はできるだけ素早く行う必要がある。

例:Log4Jロガーに注入する

Guiceはjava.util.Loggerインスタンスに注入するビルトインサポートがあり、それらは注入を受けるインスタンスの型の名称が使われる。 タイプリスナAPIを使うことによりorg.apache.log4j.Loggerに対して同様のhigh-fidelityネーミングを行うことができる。 このフォーマットのフィールドに注入してみよう。

import org.apache.log4j.Logger;
import com.publicobject.log4j.InjectLogger;

public class PaymentService {
  @InjectLogger Logger logger;

  ...
}

モジュールにてカスタムタイプリスナLog4JTypeListenerをまず登録する。 matcherを使って、どのタイプをリッスンするかを選択する。

  @Override protected void configure() {
    bindListener(Matchers.any(), new Log4JTypeListener());
  }

TypeListenerにて型のフィールドをスキャンして、Log4Jロガーを探す。 見つかったロガーフィールドそれぞれについて渡されたTypeEncounterにLog4JMembersInjectorを登録する。

  class Log4JTypeListener implements TypeListener {
    public <T> void hear(TypeLiteral<T> typeLiteral, TypeEncounter<T> typeEncounter) {
      for (Field field : typeLiteral.getRawType().getDeclaredFields()) {
        if (field.getType() == Logger.class
            && field.isAnnotationPresent(InjectLogger.class)) {
          typeEncounter.register(new Log4JMembersInjector<T>(field));
        }
      }
    }
  }

最後にLog4JMembersInjectorをロガーをセットするように実装する。 この例では、フィールドに同じインスタンスをセットするようにしている。 実際のアプリケーションでは、値を導出するか、プロバイダにリクエストするようにする。

  class Log4JMembersInjector<T> implements MembersInjector<T> {
    private final Field field;
    private final Logger logger;

    Log4JMembersInjector(Field field) {
      this.field = field;
      this.logger = Logger.getLogger(field.getDeclaringClass());
      field.setAccessible(true);
    }

    public void injectMembers(T t) {
      try {
        field.set(t, logger);
      } catch (IllegalAccessException e) {
        throw new RuntimeException(e);
      }
    }
  }