JAVA CDI 学习(1) - @Inject基本用法

CDI(Contexts and Dependency Injection 上下文依赖注入),是JAVA官方提供的依赖注入实现,可用于Dynamic Web Module中,先给3篇老外的文章,写得很不错

1、Java EE CDI Dependency Injection (@Inject) tutorial
2、Java EE CDI Producer methods tutorial
3、Java EE CDI bean scopes

此外,还有jboss官方的参考文档:http://docs.jboss.org/weld/reference/latest/en-US/html/

如果不想啃洋文,也可以继续往下看:

一、基本的Inject注入

1.1 在eclipse中先创建一个常规的maven Dynamic Web项目(不熟悉maven的,可以先看看这里),下面是完整的项目截图

JAVA CDI 学习(1) - @Inject基本用法_第1张图片

里面各package的代码,后面会给出。 项目的属性中,注意有几个属性要勾上(默认情况下,应该已经自动勾上了),如下图:

JAVA CDI 学习(1) - @Inject基本用法_第2张图片

上图右侧的圆圈,其实就是CDI 1.0使用的先决条件。

Pom.xml的内容如下:

  1 xml version="1.0" encoding="UTF-8"?>
  2 
 18 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 19     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 20     <modelVersion>4.0.0modelVersion>
 21 
 22     <groupId>cnblogsgroupId>
 23     <artifactId>cdi-web-sampleartifactId>
 24     <version>0.0.1-SNAPSHOTversion>
 25     <packaging>warpackaging>
 26     <name>cdi-web-samplename>
 27     <description>A starter Java EE 6 webapp project for use on JBoss AS 7 / EAP 6, generated from the jboss-javaee6-webapp archetypedescription>
 28 
 29     <url>http://jboss.org/jbossasurl>
 30     <licenses>
 31         <license>
 32             <name>Apache License, Version 2.0name>
 33             <distribution>repodistribution>
 34             <url>http://www.apache.org/licenses/LICENSE-2.0.htmlurl>
 35         license>
 36     licenses>
 37 
 38     <properties>
 39         
 41         
 43         <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
 44 
 45         
 46         <version.jboss.maven.plugin>7.4.Finalversion.jboss.maven.plugin>
 47 
 48         
 50         <version.jboss.bom>1.0.7.Finalversion.jboss.bom>
 51         
 55         
 56 
 57         
 58         <version.surefire.plugin>2.10version.surefire.plugin>
 59         <version.war.plugin>2.1.1version.war.plugin>
 60 
 61         
 62         <maven.compiler.target>1.6maven.compiler.target>
 63         <maven.compiler.source>1.6maven.compiler.source>
 64     properties>
 65 
 66 
 67     <dependencyManagement>
 68         <dependencies>
 69             
 77             <dependency>
 78                 <groupId>org.jboss.bomgroupId>
 79                 <artifactId>jboss-javaee-6.0-with-toolsartifactId>
 80                 <version>${version.jboss.bom}version>
 81                 <type>pomtype>
 82                 <scope>importscope>
 83             dependency>
 84             <dependency>
 85                 <groupId>org.jboss.bomgroupId>
 86                 <artifactId>jboss-javaee-6.0-with-hibernateartifactId>
 87                 <version>${version.jboss.bom}version>
 88                 <type>pomtype>
 89                 <scope>importscope>
 90             dependency>
 91         dependencies>
 92     dependencyManagement>
 93 
 94     <dependencies>
 95 
 96         
 98 
 99         
101         <dependency>
102             <groupId>javax.enterprisegroupId>
103             <artifactId>cdi-apiartifactId>
104             <scope>providedscope>
105         dependency>
106 
107         
109         <dependency>
110             <groupId>org.jboss.spec.javax.annotationgroupId>
111             <artifactId>jboss-annotations-api_1.1_specartifactId>
112             <scope>providedscope>
113         dependency>
114 
115         
117         <dependency>
118             <groupId>org.jboss.spec.javax.ws.rsgroupId>
119             <artifactId>jboss-jaxrs-api_1.1_specartifactId>
120             <scope>providedscope>
121         dependency>
122 
123         
125         <dependency>
126             <groupId>org.hibernate.javax.persistencegroupId>
127             <artifactId>hibernate-jpa-2.0-apiartifactId>
128             <scope>providedscope>
129         dependency>
130 
131         
133         <dependency>
134             <groupId>org.jboss.spec.javax.ejbgroupId>
135             <artifactId>jboss-ejb-api_3.1_specartifactId>
136             <scope>providedscope>
137         dependency>
138 
139         
140         
141         
142         <dependency>
143             <groupId>org.hibernategroupId>
144             <artifactId>hibernate-validatorartifactId>
145             <scope>providedscope>
146             <exclusions>
147                 <exclusion>
148                     <groupId>org.slf4jgroupId>
149                     <artifactId>slf4j-apiartifactId>
150                 exclusion>
151             exclusions>
152         dependency>
153 
154         
156         <dependency>
157             <groupId>org.jboss.spec.javax.facesgroupId>
158             <artifactId>jboss-jsf-api_2.1_specartifactId>
159             <scope>providedscope>
160         dependency>
161 
162         
163 
164         
166         <dependency>
167             <groupId>org.hibernategroupId>
168             <artifactId>hibernate-jpamodelgenartifactId>
169             <scope>providedscope>
170         dependency>
171 
172         
174         <dependency>
175             <groupId>org.hibernategroupId>
176             <artifactId>hibernate-validator-annotation-processorartifactId>
177             <scope>providedscope>
178         dependency>
179 
180         
181         <dependency>
182             <groupId>junitgroupId>
183             <artifactId>junitartifactId>
184             <scope>testscope>
185         dependency>
186 
187         
188         
190         <dependency>
191             <groupId>org.jboss.arquillian.junitgroupId>
192             <artifactId>arquillian-junit-containerartifactId>
193             <scope>testscope>
194         dependency>
195 
196         <dependency>
197             <groupId>org.jboss.arquillian.protocolgroupId>
198             <artifactId>arquillian-protocol-servletartifactId>
199             <scope>testscope>
200         dependency>
201 
202     dependencies>
203 
204     <build>
205         
207         <finalName>${project.artifactId}finalName>
208         <plugins>
209             <plugin>
210                 <artifactId>maven-war-pluginartifactId>
211                 <version>${version.war.plugin}version>
212                 <configuration>
213                     
214                     <failOnMissingWebXml>falsefailOnMissingWebXml>
215                 configuration>
216             plugin>
217             
218             
219             <plugin>
220                 <groupId>org.jboss.as.pluginsgroupId>
221                 <artifactId>jboss-as-maven-pluginartifactId>
222                 <version>${version.jboss.maven.plugin}version>
223             plugin>
224         plugins>
225     build>
226 
227     <profiles>
228         <profile>
229             
231             
233             <id>defaultid>
234             <activation>
235                 <activeByDefault>trueactiveByDefault>
236             activation>
237             <build>
238                 <plugins>
239                     <plugin>
240                         <artifactId>maven-surefire-pluginartifactId>
241                         <version>${version.surefire.plugin}version>
242                         <configuration>
243                             <skip>trueskip>
244                         configuration>
245                     plugin>
246                 plugins>
247             build>
248         profile>
249 
250         <profile>
251             
253             
255             
256             <id>arq-jbossas-managedid>
257             <dependencies>
258                 <dependency>
259                     <groupId>org.jboss.asgroupId>
260                     <artifactId>jboss-as-arquillian-container-managedartifactId>
261                     <scope>testscope>
262                 dependency>
263             dependencies>
264         profile>
265 
266         <profile>
267             
269             
270             <id>arq-jbossas-remoteid>
271             <dependencies>
272                 <dependency>
273                     <groupId>org.jboss.asgroupId>
274                     <artifactId>jboss-as-arquillian-container-remoteartifactId>
275                     <scope>testscope>
276                 dependency>
277             dependencies>
278         profile>
279 
280         <profile>
281             
283             
285             
287             
288             <id>openshiftid>
289             <build>
290                 <plugins>
291                     <plugin>
292                         <artifactId>maven-war-pluginartifactId>
293                         <version>${version.war.plugin}version>
294                         <configuration>
295                             <outputDirectory>deploymentsoutputDirectory>
296                             <warName>ROOTwarName>
297                         configuration>
298                     plugin>
299                 plugins>
300             build>
301         profile>
302 
303     profiles>
304 project>
pom.xml

 

1.2 model包下,会创建Product类

 1 package model;
 2 
 3 public class Product {
 4 
 5     private String productName;
 6 
 7     private String productNo;
 8 
 9     public String getProductNo() {
10         return productNo;
11     }
12 
13     public void setProductNo(String productNo) {
14         this.productNo = productNo;
15     }
16 
17     public String getProductName() {
18         return productName;
19     }
20 
21     public void setProductName(String productName) {
22         this.productName = productName;
23     }
24 
25     public String toString() {
26         return this.productName + " "    + this.productNo;
27 
28     }
29 }
Product

这个类其实是打酱油的

 

1.3 service包下,建一个ProductService接口

1 package service;
2 
3 import model.Product;
4 
5 public interface ProductService {
6 
7     Product getNewProduct();
8     
9 }
ProductService

 

1.4 service包下,再来几个实现

 1 package service;
 2 
 3 import javax.inject.Inject;
 4 
 5 import model.Product;
 6 
 7 public abstract class BaseProductServiceImpl implements ProductService {
 8     
 9     @Inject
10     protected Product product;
11     
12     
13     public abstract Product getNewProduct();
14 }
BaseProductServiceImpl

这个是实现类的基类,注意这里私有成员上打了一个注解@Inject,表示运行时将动态注入(实例化)一个Product

再来二个具体的实现类,BookProductServiceImpl生成"书籍"

 1 package service;
 2 
 3 import annotation.Book;
 4 import model.Product;
 5 
 6 @Book
 7 public class BookProductServiceImpl extends BaseProductServiceImpl {
 8 
 9     public Product getNewProduct() {
10         product.setProductName("论程序员的自我修养");
11         product.setProductNo("ISBN 999");
12         return product;
13     }
14 
15 }
BookProductServiceImpl

TelephoneProductServiceImpl生成“电话”

 1 package service;
 2 
 3 import annotation.Telephone;
 4 import model.Product;
 5 
 6 @Telephone
 7 public class TeletephoneProductServiceImpl extends BaseProductServiceImpl {
 8 
 9     public Product getNewProduct() {
10         product.setProductName("NOKIA LUMIA");
11         product.setProductNo("920");
12         return product;
13     }
14 
15 }
TeletephoneProductServiceImpl

可能有朋友注意到了,里面用到了二个自己写的注释@Book和@Telephone,接下来会讲到,这里先忽略

 

1.5 controller包下,添加IndexController类

为了能跟JSF的前台页面交互,这里需要添加一个Controller

 1 package controller;
 2 
 3 import javax.faces.bean.ManagedBean;
 4 import javax.inject.Inject;
 5 
 6 import annotation.*;
 7 import service.*;
 8 
 9 @ManagedBean(name = "Index")
10 public class IndexController {
11 
12     @Inject
13     @Book
14     private ProductService bookProductService;
15 
16     @Inject
17     @Telephone
18     private ProductService telephoneProductService;
19 
20     public ProductService getBookProductService() {
21         return bookProductService;
22     }
23 
24     public ProductService getTelephoneProductService() {
25         return telephoneProductService;
26     }
27 
28 }
29 IndexController
IndexController

好了,一下子搞了这么多代码,先停下来消化一下,这里我们模拟了分层架构:

model - 代表了业务模型层(本例中,为了简单起见,没有细分 业务模型、实体模型、以及web中的ViewModel)

service - 代表了服务层(为了简单起见,我们把接口+实现都放在一起了,实际中,可能会把这二个分开来)

controller - 这是web层MVC中的控制器层

当然,为了能展示最终的效果,我们会在后面加一个页面做为View层来提供UI

 

1.6 webapp下,新建一个index.xhtml文件,内容如下:

 1 
 2  3     xmlns:h="http://java.sun.com/jsf/html"
 4     xmlns:f="http://java.sun.com/jsf/core"
 5     xmlns:ui="http://java.sun.com/jsf/facelets">
 6 
 7 
 8 
 9     Book:
10     
#{Index.bookProductService.newProduct.toString()} 11
12
Telephone: 13
#{Index.telephoneProductService.newProduct.toString()} 14
index.xhtml

页面里几乎没啥代码,就是调用IndexController实例中的getBookProductService、getTelephoneProductService方法,进而得到相应的"服务实现类实例",最终输出产品信息

 

1.7 Inject用在什么地方了?

a) 页面显示时,IndexController里,bookProductService和telephoneProductService这二个私有成员上,都加了@Inject注解,所以运行时,这二个成员都能被实例化,但是问题来了,它们都是ProductService的接口类型,而这个接口有二个具体的实现(BookProductServiceImpl和TeletephoneProductServiceImpl),最终运行时,应该实现化哪一个呢?

关键在于另一个注解@Book和@Telephone,观察一下:BookProductServiceImpl类上我们也加了@Book,而TeletephoneProductServiceImpl上加了@Telephone,这样正好可以跟IndexControll中这二个私成成员的注释“匹配”上,所以最终系统知道私有成员bookProductService应该被实例化成BookProductServiceImpl,telephoneProductService被实例化成TeletephoneProductServiceImpl

@Book和@Telephone的代码如下:

 1 package annotation;
 2 
 3 import java.lang.annotation.Retention;
 4 import java.lang.annotation.RetentionPolicy;
 5 
 6 import javax.inject.Qualifier;
 7 
 8 @Qualifier
 9 @Retention(RetentionPolicy.RUNTIME)
10 public @interface Book {
11 
12 }
Book
 1 package annotation;
 2 
 3 import java.lang.annotation.Retention;
 4 import java.lang.annotation.RetentionPolicy;
 5 import javax.inject.Qualifier;
 6 
 7 @Qualifier
 8 @Retention(RetentionPolicy.RUNTIME)
 9 public @interface Telephone {
10 
11 }
Telephone

b) BaseProductServiceImpl中,在私成成员product上加了@Inject,这样运行时,能自动实例化Product对象

 

1.8 运行结果

jboss中部署后,浏览http://localhost:8080/cdi-web-sample/faces/index.xhtml 或http://localhost:8080/cdi-web-sample/index.jsf

JAVA CDI 学习(1) - @Inject基本用法_第3张图片

 

1.9 Method(方法)注入及Constructor(构造器)注入

刚才我们看到的都是在Field(成员)上注入,除了这种方式,也可以在Method或Constructor上注入

 1     private Product product ;
 2     
 3     /**
 4      * 演示在方法上使用@Inject注入
 5      * @param p
 6      */
 7     @Inject
 8     public void setProduct(Product p){
 9         product = p;        
10     }
11     
12     public Product getProduct(){
13         return product;        
14     }
Method Inject

上面的代码即是Method注入的示例,最后来看下构造器注入,我们再新建一个ClothProductServiceImpl用于生产服装

 1 package service;
 2 
 3 import javax.inject.Inject;
 4 
 5 import annotation.*;
 6 import model.Product;
 7 
 8 @Cloth
 9 public class ClothProductServiceImpl implements ProductService {
10 
11     private Product product;
12     
13     /**
14      * 构造器注入
15      * @param p
16      */
17     @Inject
18     public ClothProductServiceImpl(Product p ){
19         p.setProductName("A New Dress");
20         p.setProductNo("SPRIT-001");
21         product = p;
22         
23     }
24     
25     public Product getNewProduct() {        
26         return product;
27     }
28 
29 }
Constructor Inject

运行时,系统会自动给构造器ClothProductServiceImpl传递一个实例化的Product对象作为参数,以实现Product实例的注入

附文中示例源码下载:cdi-web-sample.zip

下一节,我们将学习Bean注入后的生命周期管理

你可能感兴趣的:(JAVA CDI 学习(1) - @Inject基本用法)