- 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
.
- HornetQ Messaging Developer’s Guide
- Learning Python Web Penetration Testing
- Kibana Essentials
- Production Ready OpenStack:Recipes for Successful Environments
- Microsoft System Center Orchestrator 2012 R2 Essentials
- SQL Server 2016數(shù)據(jù)庫(kù)應(yīng)用與開(kāi)發(fā)習(xí)題解答與上機(jī)指導(dǎo)
- Learning Unreal Engine Android Game Development
- C編程技巧:117個(gè)問(wèn)題解決方案示例
- Vue.js 3應(yīng)用開(kāi)發(fā)與核心源碼解析
- Get Your Hands Dirty on Clean Architecture
- 從零開(kāi)始學(xué)Python大數(shù)據(jù)與量化交易
- ASP.NET本質(zhì)論
- Learning Apache Thrift
- Developing RESTful Web Services with Jersey 2.0
- Abaqus GUI程序開(kāi)發(fā)指南(Python語(yǔ)言)