- JBoss Weld CDI for Java Platform
- Ken Finnegan
- 966字
- 2021-08-13 16:49:54
What does it mean to be a bean?
According to the CDI specification:
A bean comprises the following attributes:
- A (non-empty) set of bean types
- A (non-empty) set of qualifiers
- A scope
- Optionally, a bean EL name
- A set of interceptor bindings
- A bean implementation
Furthermore, a bean may or may not be an alternative.
Bean types
In most cases, beans acquire references to other beans through dependency injection. The point at which a bean is injected will specify the type of that bean and a set of qualifiers. With the help of the bean type and qualifiers, Weld determines the implementation of a bean to provide for injection.
A bean type can be a class or interface that is visible to clients that wish to inject it. For instance, an EJB Session Bean implementation is not visible to clients, but its @Local
interface is visible.
Note
EJB remote interfaces are not bean types of a Session Bean, and therefore they cannot be injected directly. They must be injected by defining a resource.
public class CandyStore extends CommonStore implements Store<Candy> { ... }
In this Java class, there are four bean types defined: CandyStore
, CommonStore
, Store<Candy>
, and the implicit type java.lang.Object
. An interesting point to note is that a parameterized type is considered a bean type by CDI, but only if it contains an actual type parameter and not a wildcard.
We are able to restrict which bean types are valid for any given Java class with the @Typed
annotation by providing a defined set of bean types that can be accepted. We can restrict the types from the previous example to only Store<Candy>
and the implicit java.lang.Object
type, with the following:
@Typed(Store.class) public class CandyStore extends CommonStore implements Store<Candy> { ... }
Qualifiers
A qualifier allows us to disambiguate a type without the need to leave type-safety and revert to string-based names, which we all know are fodder for runtime errors. All we need for defining a qualifier is to create an annotation that is annotated with @Qualifier
.
@Qualifier @Target( { TYPE, METHOD, PARAMETER, FIELD } ) @Retention( RUNTIME ) public @interface User {}
Here, we've defined a qualifier called User
. Specifying RUNTIME
retention informs the Java VM that we want the annotation information recorded in the class file of any bean that specifies this qualifier, so that it may be read at runtime. The values of TYPE
, METHOD
, PARAMETER
, and FIELD
specify valid locations within a bean where the qualifier may be placed.
Note
The @Retention
values are found in java.lang.annotation.RetentionPolicy
and the @Target
values are found in java.lang.annotation.ElementType
.
With our qualifier annotation, we are now able to disambiguate an injection point. The following injection point has a bean type of Account
and a qualifier of @User
:
@Inject @User Account userAccount;
The Weld container searches for a bean that matches the same bean type and all the qualifiers and each injection point that has been defined. If Weld doesn't find exactly one match, an error is reported during startup that there is an ambiguous injection point, which is Weld's way of telling you that there are too many beans that match the bean type and qualifiers.
To inform Weld that a bean has a specific qualifier, we annotate the bean class with it. The following bean would match the injection point from the previous code snippet:
@User public class UserAccount implements Account { ... }
Note
Any bean or injection point that does not explicitly specify a qualifier will have the default qualifier @Default
assigned to it.
Scope
In the previous examples, we've utilized the CDI scopes that are provided for us, but what is a scope? A scope is the means by which a bean specifies its lifecycle and the visibility of its instances.
For instance, @SessionScoped
binds a bean to a user session and is shared across all requests that execute in the context of that session.
Note
Once a bean is bound to its context, it cannot be removed from that context. The bean will remain in that context until the time the context is destroyed by the container. It's especially important to keep this in mind when developing beans that will hold large amounts of data and for how long that data needs to be retained.
Expression Language (EL)
A bean can be referenced from non-Java code if it supports Unified EL expressions, such as with JSF and JSP pages, but it requires an EL name to be defined.
The @Named
annotation specifies the EL name for a bean, as follows:
@Named("book") public class HistoryBook implements Serializable { ... }
We can now access the bean in a JSF page:
<h:outputText value="#{book.isbn}" />
If we aren't particular about what EL name a bean is given, we can specify @Named
without any value and it will default to the unqualified class name, with the first character converted to lower case. In the previous example, this would give us an EL name of historyBook
.
Alternatives
If we need to vary which implementation is chosen depending on the deployment environment or some other factor, we can create an alternative bean that can be activated when needed.
For instance, if we want to create a mock or dummy implementation that is only used in testing environments, we can write the following:
@Alternative public class DummyLogger extends LoggerImpl { ... }
It's general practice to only annotate a bean with @Alternative
when there is at least one other implementation of an interface it implements or any of its bean types, otherwise there wouldn't be anything for it to be an alternative of.
Alternatives are chosen by selecting an alternative in the CDI descriptor file, beans.xml
, of the JAR or WAR that uses it.
This topic will be covered in greater detail in Chapter 2, Dependency Injection and Lookup.
- Practical UX Design
- Visual FoxPro程序設計教程
- Bootstrap Essentials
- CKA/CKAD應試教程:從Docker到Kubernetes完全攻略
- GameMaker Programming By Example
- Bootstrap 4:Responsive Web Design
- 精通Python設計模式(第2版)
- 微服務從小白到專家:Spring Cloud和Kubernetes實戰
- Tableau 10 Bootcamp
- Visualforce Developer’s guide
- Beginning C++ Game Programming
- Building Dynamics CRM 2015 Dashboards with Power BI
- Natural Language Processing with Python Quick Start Guide
- Python第三方庫開發應用實戰
- Python趣味創意編程