官术网_书友最值得收藏!

Qualifiers

A qualifier is an annotation that has @Qualifier declared on it, which signifies to the container that this qualifier annotation can be utilized on injection points and beans to distinguish different implementations of the same bean type.

A qualifier annotation, without any members, is just:

@Qualifier
@Retention(RUNTIME)
@Target( { TYPE, METHOD, FIELD, PARAMETER } )
public @interface MyQualifier {}
Note

@MyQualifier has been defined for use on a Java type, method, field, or method parameter.

We can use field injection with @MyQualifier by:

@Inject
@MyQualifier
private Locale myLocale;

Or constructor injection:

@Inject
public Notifications(@MyQualifier Locale myLocale) {
  this.myLocale = myLocale;
}

Or an initializer method:

@Inject
public void setLocale(@MyQualifier Locale myLocale {
  this.myLocale = myLocale;
}

Lastly, producing a Locale with the @MyQualifier annotation to match the injection points:

@Produces
@MyQualifier
public Locale getMyLocale() {
  return Locale.US;
}

@Default and @Any

As we've mentioned previously, for any injection point that does not explicitly declare a qualifier annotation, the container will assume the presence of @Default, referred to as the default qualifier. The default qualifier is also assumed for any bean that does not declare one. If a bean contains the @Named annotation, it is still assumed to have @Default as @Named is not a qualifier annotation.

As the default qualifier is assumed to be present, both the beans in the following code are equivalent:

@Default
public class Ticket { ... }

public class Ticket { ... }

All beans of an application are given the @Any qualifier, whether or not there are other qualifier annotations specified. In our preceding example, Ticket would also have the @Any qualifier assumed by the container in both declarations.

@Any provides us the ability to retrieve all bean instances of a given bean type as it suppresses the addition of the default qualifier by the container.

If we had two beans of the same type, but a different set of qualifiers:

@Admin
public class Admin implements Account { ... }

public class User implements Account { ... }

We can retrieve all instances of beans that implement Account by:

@Inject
@Any
Instance<Account> accounts;

If we had forgotten to add @Any onto the preceding injection point, @Default would have been assumed by the container on the injection point and we would only have injected bean instances of type User.

Qualifier members

Qualifier annotations are also able to have members defined, which can be used as part of typesafe resolution. If a member is annotated with @Nonbinding, it will not be used during typesafe resolution and its value will have no meaning.

If we have the following qualifier annotation with members:

@Qualifier
@Retention(RUNTIME)
@Target( { TYPE, METHOD, FIELD, PARAMETER } )
public @interface Book {
  Category value();

  @Nonbinding
  String description() default "";
}

We can then create a couple of different implementations such as:

@Book(Category.FICTION)
public class FictionSearch implements BookSearch {
}

@Book(value = Category.NONFICTION, description =
"These are nonfiction books.")
public class NonFictionSearch implements BookSearch {
}

We can also define an injection point that will inject the NonFictionSearch implementation:

@Inject
@Book(Category.NONFICTION)
BookSearch search;

We can see the impact of @Nonbinding by changing @Book to the following, and re-deploy the war to an application server with Weld.

@Qualifier
@Retention(RUNTIME)
@Target( { TYPE, METHOD, FIELD, PARAMETER } )
public @interface Book {
  @Nonbinding
  Category value();

  @Nonbinding
  String description() default "";
}

As opposed to having a NonFictionSearch bean injected, we receive a DeploymentException exception with the following message:

WELD-001409 Ambiguous dependencies for type [BookSearch] with
qualifiers [@Book] at injection point [[field] @Inject @Book
org.cdibook.chapter2.qualifiermembers.Search.search]. Possible
dependencies [[Managed Bean [class
org.cdibook.chapter2.qualifiermembers.FictionSearch] with
qualifiers [@Any @Book], Managed Bean [class
org.cdibook.chapter2.qualifiermembers.NonFictionSearch] with
qualifiers [@Any @Book]]]

It might look confusing, but the previous message from Weld is very descriptive about how it informs us that there is more than one bean that is eligible for injection into the search field on Search.

主站蜘蛛池模板: 板桥市| 横峰县| 高青县| 米林县| 平罗县| 宜宾县| 彝良县| 黎川县| 嫩江县| 库尔勒市| 泾川县| 龙口市| 陇南市| 白城市| 牟定县| 兰考县| 左权县| 荆州市| 墨江| 夏津县| 邯郸县| 益阳市| 丹巴县| 瓦房店市| 台州市| 渑池县| 华宁县| 杭锦后旗| 信阳市| 大厂| 大埔区| 扎赉特旗| 应用必备| 正镶白旗| 张家川| 汝南县| 辽中县| 辽宁省| 阿克陶县| 双流县| 佛学|