Injection with CDI (Part I)
官方参考:http://docs.jboss.org/weld/reference/latest/en-US/html/index.html
https://antoniogoncalves.org/2011/04/07/injection-with-cdi-part-i/
After writing a post about how to bootstrap CDI in your environment and giving you some tips about how to incorporate CDI in an existing Java EE 6 application, I want to talk about injection. Yes, pure injection or how to inject a bean into another one. As you’ll see in this series of articles (Part II, Part III), many different cases can happen. Let’s start with a simple one : a straight forward injection.
Default injection
The simplest possible injection case is… simple. You have something, and you inject something into it. Why am I using the word something ? Because until Java EE 5 we could only inject resources (EntityManager, Datasource, JMS destinations and factories…) into certain components (EJBs and Servlets). With CDI, you can inject nearly anything into anything else.
Versions of software used for this arcticle
Java SE 1.6.0_33
GlassFish 3.1.2.2
Maven 3.0.3
To illustrate injection I’ll be using the same use case I’ve used in previous articles or in my Java EE 6 book : a CD-Book store.
The class diagram above shows the following components :
- Book is just an Entity with some attributes and named queries
- ItemEJB is a stateless EJB (with no interface) doing CRUD operations on the Book thanks to the EntityManager
- IsbnGenerator is just a POJO that generates a random ISBN number (used for the Book)
- ItemRestService is annotated with @Path (which designates a REST web service in JAX-RS) and delegates the CRUD operation to the ItemEJB
- ItemServlet is a Servlet that uses the ItemEJB to display all the books from the database
As you can see, except for the EntityManager that is injected with @PersistenceContext, all the other components use @Inject. Here is a few lines of code of the ItemEJB getting a reference of the EntityManager :
1
2
3
4
5
6
7
|
@Stateless public class ItemEJB { @PersistenceContext (unitName = "cdiPU" ) private EntityManager em; ... } |
The ItemServlet and the ItemRestService are very similar as they both inject a reference of the ItemEJB and the IsbnGenerator :
1
2
3
4
5
6
7
8
9
10
|
@WebServlet (urlPatterns = "/itemServlet" ) public class ItemServlet extends HttpServlet { @Inject private IsbnGenerator numberGenerator; @Inject private ItemEJB itemEJB; ... } |
And the IsbnGenertor has absolutely nothing special to it as it doesn’t extends from anything nor it is annotated, it’s just a POJO :
1
2
3
4
5
6
|
public class IsbnGenerator { public String generateNumber () { return "13-84356-" + Math.abs( new Random().nextInt()); } } |
In all these cases there is only one implementation to choose from (there is only ItemEJB, only one IsbnGenerator). If you only have one implementation, CDI will be able to inject it. We then talk about default injection. In fact, the code :
@Inject IsbnGenerator numberGenerator |
could have been written
@Inject @Default IsbnGenerator numberGenerator |
@Default is a built in qualifier that informs CDI to inject the default bean implementation. If you define a bean with no qualifier, the bean automatically has the qualifier @Default. The following code is identical to the previous one.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
@WebServlet (urlPatterns = "/itemServlet" ) public class ItemServlet extends HttpServlet { @Inject @Default private IsbnGenerator numberGenerator; ... } @Default public class IsbnGenerator { public String generateNumber () { return "13-84356-" + Math.abs( new Random().nextInt()); } } |
If you only have one implementation of the IsbnGenerator to inject, the default behaviour applies and a straight forward @Inject does the job. But sometimes you have to choose between several implementations, that’s where qualifiers come into play.
In this article I use the term bean, but to be more precise I should say managed bean (ie beans that are managed by CDI). ManagedBeans have been introduced in Java EE 6.
Ambiguous injection & Qualifiers
For a given bean type, there may be multiple beans which implement the type. For example, our application can have two implementations of the NumberGenerator interface : IsbnGenerator generates a 13 digits number and IssnGenerator a 8 digits number. A component that needs to generate a 13 digits number needs some way to distinguish between the two implementations. One approach would be to explicitly specify the class (IsbnGenerator) but that creates a hard dependence between the component and the implementation. Another approach would be to rely on external XML configuration to declare and inject the appropriate bean. CDI uses qualifiers, which are annotations, to get strong typing and loose coupling.
In this article I’m using injection on the attribute, meaning that the @Inject annotation is on the attribute. But with CDI you can also use setter injection or constructor injection.
Let’s say, for some reason, that the ItemServlet creates books with a 13 digits ISBN number, and the ItemRestService creates books with a 8 digits ISSN number. Both (the ItemServlet and the ItemRestService) inject a reference of the same NumberGenerator interface, which implementation will there use ? You don’t know ? CDI doesn’t know either, and this is the kind of error message you will get :
Ambiguous dependencies for type [NumberGenerator] with qualifiers [@Default] at injection point [[field] @Inject private ItemRestService.numberGenerator]. Possible dependencies [[Managed Bean [class IsbnGenerator] with qualifiers [@Any @Default], Managed Bean [class IssnGenerator] with qualifiers [@Any @Default]]]. |
That means we need to be less ambiguous and tell CDI which bean to inject where. If you come from Spring the first thing that comes to your mind is “let’s use the beans.xml file“. But as this post says, “beans.xml is not there to define beans in XML“. With CDI you use qualifiers (annotations).
There are three built-in qualifiers in CDI :
- @Default : If a bean does not explicitly declare a qualifier, the bean has a @Default qualifier
- @Any : allows the application to specify qualifiers dynamically
- @New : allows the application to obtain a new qualified bean
A qualifier represents some semantic associated with a type that is satisfied by some implementations of the type. For example, you could introduce qualifiers to represent thirteen digits number generator or eight digits number generator. In Java qualifiers are represented by annotations defined as @Target({FIELD, TYPE, METHOD}) and @Retention(RUNTIME). It is declared by specifying the @javax.inject.Qualifier meta-annotation as follow :
1
2
3
4
5
6
7
8
9
10
11
|
@Qualifier @Retention (RUNTIME) @Target ({FIELD, TYPE, METHOD}) public @interface EightDigits { } @Qualifier @Retention (RUNTIME) @Target ({FIELD, TYPE, METHOD}) public @interface ThirteenDigits { } |
As you can see, I’ve just defined two qualifiers, very easily. Right, so how do I use them now ? Better than words, a class diagram will make it clear.
First of all, the qualifiers need to be applied on the appropriate implementation. As you can see, @ThirteenDigits is applied to IsbnGenerator and @EightDigits to @IssnGenerator :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
@EightDigits public class IssnGenerator implements NumberGenerator { public String generateNumber() { return "8-" + Math.abs( new Random().nextInt()); } } @ThirteenDigits public class IsbnGenerator implements NumberGenerator { public String generateNumber() { return "13-84356-" + Math.abs( new Random().nextInt()); } } |
Then, the components that inject a reference to the NumberGenerator interface also need to use it as follow :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
@WebServlet (urlPatterns = "/itemServlet" ) public class ItemServlet extends HttpServlet { @Inject @ThirteenDigits private NumberGenerator numberGenerator; ... } @Path ( "/items" ) @ManagedBean public class ItemRestService { @Inject @EightDigits private NumberGenerator numberGenerator; ... } |
You don’t need external configuration, that’s why CDI is said to use strong typing. You can rename your implementations to whatever you want, the injection point will not change (that’s loose coupling). Note that a bean may declare multiple qualifiers. As you can see, CDI is an elegant way to have typesafe injection. But if you start creating annotations each time you need to inject something, your application will end up being very verbose. That’s when enumerations can help you.
Qualifiers with enumerations
Each time you need to choose between implementation you create an annotation. So if you need an extra two digits number generator or a ten digits number generator you create more and more annotations. Looks like we are moving from XML Hell to Annotation Hell ! One way to avoid the multiplication of annotations is to use enumeration as follow :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
@WebServlet (urlPatterns = "/itemServlet" ) public class ItemServlet extends HttpServlet { @Inject @NumberOfDigits (Digits.THIRTEEN) private NumberGenerator numberGenerator; ... } @Path ( "/items" ) @ManagedBean public class ItemRestService { @Inject @NumberOfDigits (Digits.EIGHT) private NumberGenerator numberGenerator; ... } @NumberOfDigits (Digits.THIRTEEN) public class IsbnGenerator implements NumberGenerator { public String generateNumber() { return "13-84356-" + Math.abs( new Random().nextInt()); } } @NumberOfDigits (Digits.EIGHT) public class IssnGenerator implements NumberGenerator { public String generateNumber() { return "8-" + Math.abs( new Random().nextInt()); } } |
As you can see I got rid of the @ThirteenDigits and @EightDigits qualifiers and I’m using the single qualifier @NumberOfDigits which as an enumerations as a value (in my example @EightDigits). This is the code you need to write :
1
2
3
4
5
6
7
8
9
10
11
12
13
|
@Qualifier @Retention (RUNTIME) @Target ({FIELD, TYPE, METHOD}) public @interface NumberOfDigits { Digits value(); } public enum Digits { TWO, EIGHT, TEN, THIRTEEN } |
Conclusion
I don’t know about you, but I love it. I really like the way CDI wires beans together without XML, just with pure Java in a type-safe way. Ok, ok, I admit, not everything is beautiful. The first thing I see is the multiplication of annotations in your code. Thanks to enumerations, this can be limited. The other point I can see is the IDE support. Your IDE needs to be cleaver to know that :
@Inject @NumberOfDigits (Digits.EIGHT) NumberGenerator numberGenerator |
refers to IssnGenerator. But here I’m talking without really knowing much about the topic. I use Intellij IDEA and the CDI support is just amazing. I can navigate from bean to bean without worrying about knowing the implementation. I suppose NetBeans might have some kind of support… but I wonder if Eclipse does ;o)
The next article will cover the different available injection points, so stay tuned.
Download
Download the code, give it a try, and give me some feedback.
References
- Dependency Injection and replacing dependencies in CDI/Weld
- TOTD #144: CDI @Produces for container-managed @Resource
- Weld – JSR-299 Reference Implementation
This is the second post based on pure CDI Injection (see Part I) after having talked about how to bootstrap CDI in several environments and how to add CDI to an existing Java EE 6 application. In this post I quickly want to show the different injection points in CDI : field, constructor and setter. To illustrate these different injection points I’ll use a subset of the previous example : a servlet injecting an ISBN generator POJO :
Field injection
Until now, in all the previous posts, you’ve seen the @Inject annotation put on fields (attributes).
1234567891011@WebServlet
(urlPatterns =
"/itemServlet"
)
public
class
ItemServlet
extends
HttpServlet {
@Inject
@ThirteenDigits
private
NumberGenerator numberGenerator;
@Inject
private
ItemEJB itemEJB;
...
}
As you can see in the code above, the @Inject and the qualifiers (here @ThirteenDigits) annotate an attribute. But like many other injection frameworks, in CDI you can also have constructor and setter injection.
Constructor injection
Instead of annotating the attributes, you can add the @Inject annotation on a constructor. If you then need to use qualifiers, you can add them to the attributes of the constructor as follow :
12345678910111213@WebServlet
(urlPatterns =
"/itemServlet"
)
public
class
ItemServlet
extends
HttpServlet {
private
NumberGenerator numberGenerator;
private
ItemEJB itemEJB;
@Inject
public
ItemServlet(
@ThirteenDigits
NumberGenerator numberGenerator, ItemEJB itemEJB) {
this
.numberGenerator = numberGenerator;
this
.itemEJB = itemEJB;
}
...
}
As you can see, the @Inject is not on the field but on the constructor. On the other hand, @ThirteenDigits doesn’t qualify the constructor but the numberGenerator parameter itself (which is logical). You can also mix field and constructor injection if you want (below I use constructor injection and attribute injection on the EJB) :
1234567891011121314@WebServlet
(urlPatterns =
"/itemServlet"
)
public
class
ItemServlet
extends
HttpServlet {
private
NumberGenerator numberGenerator;
@Inject
private
ItemEJB itemEJB;
@Inject
public
ItemServlet(
@ThirteenDigits
NumberGenerator numberGenerator) {
this
.numberGenerator = numberGenerator;
}
...
}
But the rule is : you can only have one constructor injection point. The container is the one doing injection, not you (you can’t invoke a constructor in a managed environment, well, you can, but it will not work as you expect). There is only one bean constructor allowed so the container can do its job of injecting the right references. The following is invalid :
123456789101112131415161718@WebServlet
(urlPatterns =
"/itemServlet"
)
public
class
ItemServlet
extends
HttpServlet {
private
NumberGenerator numberGenerator;
private
ItemEJB itemEJB;
@Inject
public
ItemServlet(
@ThirteenDigits
NumberGenerator numberGenerator, ItemEJB itemEJB) {
this
.numberGenerator = numberGenerator;
this
.itemEJB = itemEJB;
}
@Inject
public
ItemServlet(
@ThirteenDigits
NumberGenerator numberGenerator) {
this
.numberGenerator = numberGenerator;
}
...
}
If you have more than one bean constuctor, this is what you get (the error code and message is Weld specific of course) :
WELD-000812 Cannot determine constructor to use for public@WebServlet class ItemServlet. Possible constructors [[constructor] @Inject public ItemServlet(NumberGenerator, ItemEJB), [constructor] @Inject public ItemServlet(NumberGenerator)]
On the other hand, it is syntactically legal to have field and constructor injection at the same time (but useless) :
123456789101112131415@WebServlet
(urlPatterns =
"/itemServlet"
)
public
class
ItemServlet
extends
HttpServlet {
@Inject
@ThirteenDigits
private
NumberGenerator numberGenerator;
@Inject
private
ItemEJB itemEJB;
@Inject
public
ItemServlet(
@ThirteenDigits
NumberGenerator numberGenerator, ItemEJB itemEJB) {
this
.numberGenerator = numberGenerator;
this
.itemEJB = itemEJB;
}
...
}
Setter injection
The other choice is to use setter injection which looks like constructor injection. You annotate the setter with @Inject and you qualify the parameters :
1234567891011121314151617@WebServlet
(urlPatterns =
"/itemServlet"
)
public
class
ItemServlet
extends
HttpServlet {
private
NumberGenerator numberGenerator;
private
ItemEJB itemEJB;
@Inject
public
void
setNumberGenerator(
@ThirteenDigits
NumberGenerator numberGenerator) {
this
.numberGenerator = numberGenerator;
}
@Inject
public
void
setItemEJB(ItemEJB itemEJB) {
this
.itemEJB = itemEJB;
}
...
}
When you use constructor or setter injection you need to apply your qualifiers to a parameter. So make sure you have the right @Targets (java.lang.annotation.ElementType.PARAMETER) definition :
12345@Qualifier
@Retention
(RUNTIME)
@Target
({FIELD, TYPE, METHOD, PARAMETER})
public
@interface
ThirteenDigits {
}
Conclusion
One question you could ask (and that’s the one I asked to Pete Muir) is : “when do you use field over constructor or setter injection ?”. There is no real technical answer except that it’s your personal taste. In a managed environment, the container is the one doing all the injection work, it just needs the right injection points. However, with constructor or setter injection you can add some logic if needed (not with field injection). But it looks like setter injection was added for backward compatibility with existing Java Beans.The next article will cover producers, so stay tuned.
Download
Download the code, give it a try, and give me some feedback.
References
If you follow this blog you should know that latelly I’ve been writing (and talking) about CDI (Contexts and Dependency Injection). CDI has many aspects to it but until now I’ve focused onhow to boostrap CDI in several environments, how to add CDI to an existing Java EE 6 application, and more recently how to use injection with CDI. Actually this post is the third on CDI Injection : Part I focused on default injection and qualifiers, and Part II on all the possible injection points (field, constructor and setters). In this post I’ll explainproducers or “how you can inject anything anywhere in a type safe manner“.
Injecting just beans ?
Until now I’ve shown you how to inject beans with a simple @Inject. If we focus on the book number generator example I’ve been using, we have a Servlet and a RESTService being injected an implementation of the NumberGenerator interface. Thanks toqualifiers, the servlet can specifically ask to get the IsbnGenerator by specifying the @ThirteenDigit qualifier on the injection point and the rest service an IssnGenerator with a @EightDigits (check my first post). The following class diagram shows you some combinations of bean injection :
But as you can see, all this is are beans injecting other beans. Can we just inject beans with CDI ? The answer is no, you can inject anything anywhere.
Producers
Yes, you can inject anything anywhere, the only thing you have to do is produce the thing you want to inject. For that, CDI hasproducers (a nice implementation of the Factory pattern) A producer exposes any sort of :
- Class : unrestricted set of bean types, superclass, and all interfaces it implements directly or indirectly
- Interface : unrestricted set of bean types, interfaces it extends directly or indirectly, and java.lang.Object
- Primitive and Java array type
So by that you can inject a java.util.Date, java.lang.String or even an int. Let’s start by producing and injecting some data types and primitives.
Producing data types and primitives
One example of injecting anything anywhere is the possibility to inject data types or primitives. So let’s inject a String and an int. For that I need to add extra classes to our model. Until now, the IsbnGenerator would generate a random number like 13-124-454644-4. I can say that this number is made of a String that acts like a prefix (13-124) and an int that acts like a suffix (4). The following class diagram shows the two new classes PrefixGenerator and PostfixGeneratorthat will be used by the number generators :
If we look at the code of the PrefixGenerator for example, you can see that the class itself is not annotated by any qualifier, but the methods are. The method getIsbnPrefix returns a String that is qualified with @ThirteenDigits. This String is produced by CDI (thanks to @Produces), meaning that you can now inject it with @Inject using its qualifier (@ThirteenDigits)
123456789101112public
class
PrefixGenerator {
@Produces
@ThirteenDigits
public
String getIsbnPrefix() {
return
"13-84356"
;
}
@Produces
@EightDigits
public
String getIssnPrefix() {
return
"8"
;
}
}
And now look carefully at the class PostfixGenerator. The code is exactly the same as previously except in this case we produce an intthat can now be injected.
123456789101112public
class
PostfixGenerator {
@Produces
@ThirteenDigits
public
int
getIsbnPostfix() {
return
13
;
}
@Produces
@EightDigits
public
int
getIssnPostfix() {
return
8
;
}
}
So now let’s change the way an ISBN number is generated. The bean IsbnGenerator now injects both a String and an int with @Inject @ThirteenDigits. You understand now what strong typing means with CDI. Using the same syntax (@Inject @ThirteenDigits), CDI knows that it needs to inject a String, an int or an implementation of a NumberGenerator.
12345678910111213@ThirteenDigits
public
class
IsbnGenerator
implements
NumberGenerator {
@Inject
@ThirteenDigits
private
String prefix;
@Inject
@ThirteenDigits
private
int
postfix;
public
String generateNumber() {
return
prefix +
"-"
+ Math.abs(
new
Random().nextInt()) +
"-"
+ postfix;
}
}
Injecting Java EE resources with producer fields
So if CDI can inject anything anywhere, if CDI can even inject Strings and integers, what about Java EE resources ? That’s another story and producers are here to help. As I’ve said before, CDI is all about type safety : CDI doesn’t like Strings, so there is no way to inject a resource by its JNDI name such as @Inject(name=”jms/OrderQueue”). A common example is the entity manager. This is how you must inject it in Java EE 6 if you don’t use CDI :
1234567@Stateless
public
class
ItemEJB {
@PersistenceContext
(unitName =
"cdiPU"
)
private
EntityManager em;
...
}
So why can’t you just @Inject an entity manager? If you remember my first post about ambiguous injection, this is the same problem. You can have several persistence units (named with a string), so if you just use an @Inject, CDI will not know which persistence unit to inject. Instead you must produce the entity manager first, give it a name (if you don’t want the @Default) and then an @Inject as follow :
1234567public
class
DatabaseProducer {
@Produces
@PersistenceContext
(unitName =
"cdiPU"
)
@BookStoreDatabase
private
EntityManager em;
}
The DatabaseProducer class uses the @PersistenceContext to inject the entity manager with the persistence unit cdiPU. It gives it a name using a qualifier (@BookStoreDatabase) and produces it so it can now be injected in an EJB as follow :
12345678@Stateless
public
class
ItemEJB {
@Inject
@BookStoreDatabase
private
EntityManager em;
...
}
Another nice use case is to produce JMS factories and destinations. @Resource allows you to get a JNDI reference to a specific JMS factory or destination, the qualifier @Order gives it a name, and the @Produces allows you to inject it :
12345678public
class
JMSResourceProducer {
@Produces
@Order
@Resource
(name =
"jms/OrderConnectionFactory"
)
private
QueueConnectionFactory orderConnectionFactory;
@Produces
@Order
@Resource
(name =
"jms/OrderQueue"
)
private
Queue orderQueue;
}
Now your EJB can use @Inject in a type-safe way :
12345678910@Stateless
public
class
ItemEJB {
@Inject
@Order
private
QueueConnectionFactory orderConnectionFactory;
@Inject
@Order
private
Queue orderQueue;
...
}
Producing Java EE resources with producer methods
The examples above are pretty simple : produce a field and you can then inject it. That’s called producer field. But sometimes you need a more complex business logic to produce a bean, that’s what we called producer method. Let’s take another use case. When you need to send a JMS message you always end up injecting a JMS Factory, a destination (queue or topic) creating a connection, then a session and so on until you actually send your message. Because this code is repetitive and error prone, why not externalize all of if into a single class and produce a session so the other components can use when sending a message. This class could look something like that :
1234567891011121314151617public
class
JMSResourceProducer {
@Resource
(name =
"jms/OrderConnectionFactory"
)
private
QueueConnectionFactory orderConnectionFactory;
@Produces
@Order
@Resource
(name =
"jms/OrderQueue"
)
private
Queue orderQueue;
@Produces
@Order
public
QueueConnection createOrderConnection()
throws
JMSException {
return
orderConnectionFactory.createQueueConnection();
}
@Produces
@Order
public
QueueSession createOrderSession(
@Order
QueueConnection conn)
throws
JMSException {
return
conn.createQueueSession(
true
, Session.AUTO_ACKNOWLEDGE);
}
}
First, the class uses the @Resource to get a reference of the QueueConnectionFactory and Queue. For the same reason I just explain above, you can have several JMS factories and destinations and you must distinguish them by their JNDI name. And because CDI does not allow you to give a string name on an injection point, you must still use @Resource instead of @Inject. The createOrderConnection method take a QueueConnectionFactory creates a QueueConnection and produces it (while giving it the name of @Order). If you look carefully at the method createOrderSession it takes the produced QueueConnection and creates a QueueSession. An external component then just needs to inject the JMS session without going through the process of creating it :
1234567891011121314151617@Stateless
public
class
ItemEJB {
@Inject
@Order
private
QueueSession session;
@Inject
@Order
private
Queue orderQueue;
private
void
sendOrder(Book book)
throws
Exception {
QueueSender sender = session.createSender(orderQueue);
TextMessage message = session.createTextMessage();
message.setText(marshall(book));
sender.send(message);
}
...
}
Producing and… disposing
I can hear you saying “ok, that’s nice, I have an external class doing all the plumbing and creating a connection and a session…. but who is going to close it ?“. Indeed, someone needs to free these resources by closing them. And that’s when CDI brings you another nice bit of magic : @Disposes.
12345678910111213141516171819202122232425public
class
JMSResourceProducer {
@Resource
(name =
"jms/OrderConnectionFactory"
)
private
QueueConnectionFactory orderConnectionFactory;
@Produces
@Order
@Resource
(name =
"jms/OrderQueue"
)
private
Queue orderQueue;
@Produces
@Order
public
QueueConnection createOrderConnection()
throws
JMSException {
return
orderConnectionFactory.createQueueConnection();
}
@Produces
@Order
public
QueueSession createOrderSession(
@Order
QueueConnection conn)
throws
JMSException {
return
conn.createQueueSession(
true
, Session.AUTO_ACKNOWLEDGE);
}
public
void
closeOrderSession(
@Disposes
@Order
QueueConnection conn)
throws
JMSException {
conn.close();
}
public
void
closeOrderSession(
@Disposes
@Order
QueueSession session)
throws
JMSException {
session.close();
}
}
To ask CDI to close a resource you just need to create a method which signature is the same as the one that created it (createOrderSession(@Order QueueConnection conn) creates a session and closeOrderSession(@Order QueueConnection conn) closes it) and add a @Disposes. CDI will dispose the resources in the right order (session first, connection second) for you. I haven’t mentioned it yet but CDI will create and dispose resources depending on the scope (resquest, session, application, conversation…). But that’s for another post.
Conclusion
As you’ve seen in my previous posts (Part I, Part II), CDI is about injection (I’ll explain other topics later). So far I’ve been showing you how to inject beans, but you know now that you can inject anything (String, integer, entity manager, JMS factories…) anywhere (in POJOs, Servlets, EJBs…). You just need to produce what you need to inject (either with field producers or method producers).
The next article will cover alternatives, so stay tuned.Download
Download the code, give it a try, and give me some feedback.
References
Injection with CDI (Part I)的更多相关文章
- JAVA CDI 学习(4) - @Alternative/@Default/@Any & Extension
前面几节学习到的CDI内容,基本上都是hard-code,以硬编码的方式在代码里指定注入类型,这并非依赖注入的本意,依赖注入的优势之一在于“解耦”,这一节我们将学习如何利用配置来动态注入的类型及属性初 ...
- JAVA CDI 学习(1) - @Inject基本用法
CDI(Contexts and Dependency Injection 上下文依赖注入),是JAVA官方提供的依赖注入实现,可用于Dynamic Web Module中,先给3篇老外的文章,写得很 ...
- Apache CXF 3.0: CDI 1.1 Support as Alternative to Spring--reference
With Apache CXF 3.0 just being released a couple of weeks ago, the project makes yet another importa ...
- JBoss 系列六十九:CDI 基本概念
概述 如果说EJB,JPA是之前JEE(JEE5及JEE5之前)中里程碑式的规范,那么在JEE6,JEE7中CDI可以与之媲美,CDI(Contexts and Dependency Injectio ...
- JBoss 系列七十:一个简单的 CDI Web 应用
概述 本文通过一个简单的 CDI Web 应用演示dependency injection, scope, qualifiers 以及EL整合.应用部署完成后我们可以通过http://localhos ...
- CDI服务
前言 CDI(Contexts and Dependency Injection 上下文依赖注入),是JAVA官方提供的依赖注入实现,可用于Dynamic Web Module中,将依赖注入IOC/D ...
- CDI Features
概述 如果说EJB,JPA是之前JEE(JEE5及JEE5之前)中里程碑式的规范,那么在JEE6,JEE7中CDI可以与之媲美,CDI(Contexts and Dependency Injectio ...
- Container/Injection
1.容器的历史 容器概念始于 1979 年提出的 UNIX chroot,它是一个 UNIX 操作系统的系统调用,将一个进程及其子进程的根目录改变到文件系统中的一个新位置,让这些进程只能访问到这个新的 ...
- CDI feature
CDI Java EE的上下文和依赖注入(Contexts and Dependency Injection for Java EE,CDI),CDI是即将完成的Java EE 6平台的关键组成部分, ...
随机推荐
- Mybatis 配置resultMap一对多关联映射
resultMap配置: 引用: PO类: 接口: 测试: public class UserMapperTest { private SqlSessionFactory sqlSessionFact ...
- 手机端图像编辑上传-cropper
编辑头像,实现相册,照像功能,并能缩放裁剪功能,可自定义UI,引用'cropper.js', 'exif.js' /*初始化裁剪插件*/ var screenWidth = $(window).wid ...
- 关于 ajax
1.type 提交类型 get /post 2.async 默认true 异步 3.cache 默认 true 读取缓存 false不读取缓存 会在请求后面 添加一个时间戳 https://www. ...
- InputFormat的数据划分、Split调度、数据读取
在执行一个Job的时候,Hadoop会将输入数据划分成N个Split,然后启动相应的N个Map程序来分别处理它们.数据如何划分?Split如何调度(如何决定处理Split的Map程序应该运行在哪台Ta ...
- git分支操作2
1.创建分支 git branch <分支名> 会自动复制主分支上的代码. 2.查看当前分支 git branch -v 3.切换分支 git checkout < ...
- Django--cookie 和 session
一 . 会话跟踪 简单来说就是如果谢霆锋登录了淘宝,然后他点击淘宝内的任何连接就不需要在登录了,这是由于这个会话中数据共享, 也就是会话跟踪, 我们都知道http协议是短连接 无状态的,也就是说你登录 ...
- linux pstree命令
pstree命令可以使进程以tree的形式显示 pstree -ssystemd─┬─UVPHostd───6*[{UVPHostd}] ├─acpid ├─2*[agetty] ├─crond ├─ ...
- python数据结构与算法第五天【顺序表】
1.列表存储的两种方式 (1)元素内置方式 采用元素内置的方式只能存放同类型元素的数据类型,例如列表中的元素都为整形,元素类型相同,每个元素存放的地址空间大小也相同,则列表中每个元素都是顺序存放的 ( ...
- SQL Server与SQL Server Express的区别
SQL Server Express 2005(以下简称 SQLExpress) 是由微软公司开发的 SQL Server 2005(以下简称 SQL2005)的缩减版,这个版本是免费的,它继承了 S ...
- Web API2 使用默认Identity
当您选择个人账户在Web API项目模板,项目包含一个令牌授权服务器验证用户凭证和问题.下面的图显示了相同的凭证流的Web API组件. 发送一个未经授权的请求 首先,运行应用程序并单击按钮调用的AP ...