Weld(CDI)教程

本文作者: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

转载请与作者联系。


你可能感兴趣的:(CDI,seam,weld,教程,tutorial)