- JBoss Weld CDI for Java Platform
- Ken Finnegan
- 642字
- 2021-08-13 16:49:55
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
.
- DBA攻堅指南:左手Oracle,右手MySQL
- Spring Cloud Alibaba核心技術與實戰案例
- JavaScript+jQuery網頁特效設計任務驅動教程(第2版)
- 認識編程:以Python語言講透編程的本質
- Python Deep Learning
- ASP.NET動態網頁設計教程(第三版)
- Mastering macOS Programming
- Flux Architecture
- R Deep Learning Cookbook
- Learning OpenStack Networking(Neutron)
- Spring核心技術和案例實戰
- SQL Server數據庫管理與開發兵書
- Node學習指南(第2版)
- 精通Spring:Java Web開發與Spring Boot高級功能
- 前端架構設計