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

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.

主站蜘蛛池模板: 岳阳市| 绥滨县| 平乐县| 江源县| 乐业县| 铅山县| 永安市| 崇义县| 红安县| 哈巴河县| 东丽区| 遵化市| 马关县| 滁州市| 高平市| 满城县| 临颍县| 包头市| 静安区| 安国市| 赤水市| 城市| 桂林市| 滁州市| 宁河县| 太白县| 南阳市| 逊克县| 海安县| 北票市| 怀远县| 东至县| 沁阳市| 张家口市| 泸西县| 陈巴尔虎旗| 黄大仙区| 万宁市| 大荔县| 长治县| 扬中市|