天天看点

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

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

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

一、基本的Inject注入

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

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

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

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

Pom.xml的内容如下:

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

pom.xml

1.2 model包下,会创建Product类

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

Product

这个类其实是打酱油的

1.3 service包下,建一个ProductService接口

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

ProductService

1.4 service包下,再来几个实现

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

BaseProductServiceImpl

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

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

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

BookProductServiceImpl

TelephoneProductServiceImpl生成“电话”

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

TeletephoneProductServiceImpl

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

1.5 controller包下,添加IndexController类

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

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

IndexController

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

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

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

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

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

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

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

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的代码如下:

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

Book

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

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基本用法

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

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

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

Method Inject

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

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

Constructor Inject

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