レベルエンター山本大のブログ

面白いプログラミング教育を若い人たちに

BLOCKVROCKリファレンス目次はこちら

Guice User's Guide ■15. Annotations With Attributes

属性つきのアノテーション

If you can get by with marker annotations alone, feel free to skip to the next section.

もし、あなたがマーカーアノテーションだけでやっていくことができるなら、遠慮なく次のセクションまでスキップしてください。

You can also bind to annotation instances, i.e. you can have multiple bindings with the same type and annotation type, but with different annotation attribute values. If Guice can't find a binding to an annotation instance with the necessary attribute values, it will look for a binding to the annotation type instead.

アノテーションインスタンスをバインドすることもできます。たとえば、同じTypeとアノテーションTypeにもかかわらず、異なったアノテーション属性値がある複数のバインディングを持つことができます。もしGuiceが必要な属性値で、アノテーションインスタンスバインディングを見つける事が出来なかったら、代わりにアノテーションタイプとしてバインディングを探します。

Say for example we have a binding annotation @Named with a single string attribute value.

例えば、一つのString属性値がある@Namedバインディングアノテーションを持っているとしましょう。

@Retention(RUNTIME)
@Target({ FIELD, PARAMETER })
@BindingAnnotation
public @interface Named {
  String value();
}

If we want to bind to @Named("Bob"), we first need an implementation of Named. Our implementation must abide by the Annotation contract, specifically the implementations of hashCode() and equals().

@Named("Bob")にバインドしたいと思うなら、まずはNamedの実装が必要です。 実装にはAnnotation規約を守って、明示的にhashCode()とequals()を実装しなけれなければなりません。

class NamedAnnotation implements Named {
  final String value;

  public NamedAnnotation(String value) {
    this.value = value;
  }

  public String value() {
    return this.value;
  }

  public int hashCode() {
    // This is specified in java.lang.Annotation.
    return 127 * "value".hashCode() ^ value.hashCode();
  }

  public boolean equals(Object o) {
    if (!(o instanceof Named))
      return false;
    Named other = (Named) o;
    return value.equals(other.value());
  }

  public String toString() {
    return "@" + Named.class.getName() + "(value=" + value + ")";
  }

  public Class<? extends Annotation> annotationType() {
    return Named.class;
  }
}

Now we can use this annotation implementation to create bindings to @Named.

さてこれで、バインディングを@Namedで作るためのこのアノテーションの実装を使うことができます。

bind(Person.class)
  .annotatedWith(new NamedAnnotation("Bob"))
  .to(Bob.class);

This may seem like a lot of work compared to string based identifiers used by other frameworks, but keep in mind that you can't do this at all with string-based identifiers. Also, you'll find that you get a lot of reuse out of binding annotations.

多くの処理が、他のフレームワークで使用されるストリングベースの識別子の比較と同じように見えるかもしれませんが、ストリングベースの識別子では、これが全くできないのを覚えておいてください。また、バインディングアノテーションが、高い再利用性を持っているのがわかるでしょう。

Since identifying a binding by name is such a common use case, Guice provides a production-worthy implementation of @Named in com.google.inject.name.

名前によるバインディングの識別は、一般的なユースケースなので、Guiceはcom.google.inject.nameの@Namedという実装を提供しています。