本文作者:Tony Lee (http://blog.niinoo.com)首发地址:http://my.oschina.net/niinoo/blog/38310
转载请与作者联系。
-- 简介
CDI - Context Dependency Injection 上下文依赖注入:Java EE 6中定义的规范标准,编号:JSR-299。定义了一系列简化Java开发的功能。CDI已经超出一个框架的定义,升华到一种开发模型。这个开发模型不会去限制你必须将代码分为几层,不限制你必须写ORM、持久化、业务代码等,甚至不限制你到底是开发WEB程序还是客户端程序。
CDI的思想来源于几个开源项目:Seam、Guice、Spring However。不过CDI在集合了这几个框架的有点之外,克服了各自的缺点。
CDI只是一个标准(Java Community Process - JCP),不是一个具体的框架,不同的应用服务器有其自己的实现,比如JBoss AS的CDI名叫Weld。
-- 什么样的类可以用来注入
定义比较复杂,有很多巴拉巴拉的东西,实际上不用太关心,遇到问题在Google就行了。下面来看个最简单的可以用来注入的类:
package greetings; public class Greeting { public String greet(String name) { return "Hello, " + name + "."; } }
就这么简单!然后你就可以将手往上空一伸,心里默念想要的东西,虚空一抓,想要的类就在你手中了,敲到电脑里面,打完收工!如下:
import javax.inject.Inject; public class Printer { @Inject Greeting greeting; ... }
就应该这样么!什么新技术出来以后要让人云里雾里,有必要么!既然是新技术,就是要能简化我们的开发,延长我们的生命!如果什么新技术出来以后缩短了我们的生命,就该坚决排斥!CDI是每个Java开发人员都必须使用起来的技术!除非你嫌时间太多,生命太长!用了CDI,你不必写XML了,不必配置了,不必new了!所要做的,就是在想用的时候,敲一个@I然后在弹出提示中选择、回车,搞定!
回到正题。上面Greeting类的写法,与下面的写法一模一样:
package greetings; import javax.enterprise.inject.Default; @Default public class Greeting { public String greet(String name) { return "Hello, " + name + "."; } }
实际上在你用了CDI以后,它会自动给你加上@Default
“它是谁?”我问。
耳边响起一个老者的声音:“你不认识,跟你说了你也不认识。等你见到的时候会给你介绍的,现在说了你还是不认识……”
“既然@Default等于是阴魂,不可能散掉,那么不难想到,会不会还有其他不干净的东西我看不到的?”我继续问到。
“这东西叫Qualifier,现在就只告诉你这么多,别多想,也不用多想,反正牲畜无害。”耳边的声音见见远去。
-- Scope,范围,作用域,生存周期……
既然CDI的作用是在我想要那个类的时候,向上伸手就能抓到我想要的,那么难免就会出现一个问题:如果我头顶上有一大堆东西飘来飘去,或者有两个长得一样的东西分别飘在我头顶1cm处于10cm处,我该抓谁敲进电脑呢?这就需要Scope来将头顶的东西整理一下了。对于WEB开发,Scope会将你头顶的空间分为五层,就好比大气中平流层与对流层的区别。分别如下所列:
1)@Dependent:不在你头顶scope多管闲事将你的头放在这一层了,既然你不可能将你的头敲进电脑(如果能将电脑放进我的头里面又不影响我活着的状态的话,我倒是比较乐意),那就别多管这个东西了
2)@RequestScoped:头顶1cm处
3)@SessionScoped:头顶10cm处
4)@ApplicationScoped:头顶50cm处
5)@ConversationScoped:这东西是一个叫Gaving King的美国人作弊加进来的东西,通常情况下游离于头顶1cm到10cm之间,不过特殊情况它会大脑发热上下乱窜,甚至飞到外太空去。通常这个东西只能在一个叫做JSF的环境内生存。
当然,一个类会活在哪一层的世界,都是由你决定的,比如:
import javax.inject.Inject; import javax.enterprise.context.RequestScoped; @RequestScoped public class Printer { @Inject Greeting greeting; ... }
这样你就让Printer活在你头顶大约1cm左右的地方了。你可以给它起个小名,让你在某些地方(记住,很特定的某些地方)能够通过小名找到它:
@Named @RequestScoped public class Printer { @Inject @Informal Greeting greeting; ... }
@Named后面什么都没有,意味着你偷懒,让他大名小名都一样,虽然我通常喜欢这样偷懒。不过如果你想让它叫起来亲切一点,可以在后面加上一个比较平易近人的名字:
@Named("MyPrinter")
-- 如何在项目中使用CDI
同样,足够简单,只要在WEB-INF目录下面加一个名叫beans.xml的空文件就行了。
什么?连JAR包都不用?
CDI的JAR包这东西应该由容器提供(天上的众神告诉你)。
那为什么要加一个空文件?
你总要做点事情让我们知道你想用CDI吧,不然我怎么知道该不该帮你?现在这社会,路上倒个老人都得问问清楚再扶,何况你这么阴险的家伙……
-- 注入
既然名称叫做上下文依赖注入,那么首先看看到底是怎么注入的。
· 往哪里注入(3种)
public class Checkout { private final ShoppingCart cart; @Inject public Checkout(ShoppingCart cart) { this.cart = cart; } }
↑ 注入到构造方法。一个类只能有一个注入的构造方法
public class Checkout { private ShoppingCart cart; @Inject void setShoppingCart(ShoppingCart cart) { this.cart = cart; } }
public class Checkout { private @Inject ShoppingCart cart; }
↑ 注入到类属性。不需要getter与setter!
-- 注入的顺序:
1)构造方法
2)类属性
3)方法注入
4)@PostConstruct
知道以上东西,基本上已经能够将以前的开发工作量减少很多了。后面的东西就属于“高级”部分了。
本文作者:Tony Lee (http://blog.niinoo.com)首发地址:http://my.oschina.net/niinoo/blog/38310
转载请与作者联系。