Eye on CDI:Weld, Seam 3 and Beyond
目标:
- JEE的长期挑战
- 我有一个解决方案,但是……
- CDI是什么?
- Weld
- Seam 3
JEE的长期挑战
太多bean,太少的共同基础……
上下文滥用!—— HttpSession —— 为什么?
- Servlet上下文模型太粗。
- 不能反映现实世界的用法。
我有一个解决方案,但是……
- Seam提出:
- 转变任何东西为一个“组件”。
- 一类“东西”。
- 引入双向注入。
- 使依赖注入为有状态的和动态的。
- 结合了JSF和EJB。
- 增加了对话上下文和业务流程上下文。
- 转变任何东西为一个“组件”。
- 但是,Seam仍然是非JEE 的。
解决方案:上下文和依赖注入
- JSR-299 —— 用于JEE的上下文和依赖注入。
- JEE6的核心部分。
- 帮助统一bean模型。
- 明确定义的上下文,可以绑定有状态bean给它们,并管理生命周期。
- 增加依赖注入给JEE,并使它成为类型安全。
- 引入了一个事件通知系统。
- 使用拦截器,鼓励松耦合。
- 重新定义拦截器为装饰器,用于细粒度控制。
- 集成统一的EL,桥接JSF。
- 引入了一个SPI,扩展JEE —— 走向自己的JEE7!
CDI的关系
- 规范 —— JSR-299 —— CDI
- 也集成了JSR-330的元素
- 参考实现 —— Weld
- TCK —— 技术兼容工具包
- 实现 —— Seam 3
- TCK —— 技术兼容工具包
- 参考实现 —— Weld
- 也集成了JSR-330的元素
名字代表什么?解决方案的历史。
- 开始使用WebBeans。
- 更多涉及“Web”,而少涉及“Beans”。
- 规范改为CDI。
- 参考实现最初称为 WebBeans。
- 委员会异议。
- 参考实现最命名为Weld。
- 当谷歌搜索信息时,你仍然会看见提及到“WebBeans”,并且甚至在规范的文件名仍然是“WebBeans”。
统一Bean模型
管理Bean细节
- 任何被容器管理的组件都是一个Bean。
- 管理Bean建立的基本规范。
- 拦截器
- 生命周期回调
- 资源注入
- 在JEE6及之后中,其他的规范建立在这个基础之上。
- CDI
- EJB
- 等等……
CDI Beans —— 我们回到“管理Beans”
- CDI增加以下内容到管理Bean的服务:
- 自动发现
- 通过beans.xml选择加入
- Bean类型
- 有一个“家族”的bean类型的能力:
- Qualifiers (在设计时选择)
- Alternatives(在部署时选择)
- Producers(在运行时选择)
- 自动发现
- 域的通告和联接
- EL名字(可选的)
- 直接暴露bean给JSFs或JSPs
- 拦截器绑定
CDI Bean例子
public class Bike {
public String returnManufacturer() {
return "Made by JBoss";
}
}
//相同的Bean作为一个EJB
@Stateful public class Bike {
.....
//
相同的Bean暴露给一个JSF
@Named
public class Bike {
.....
明确定义的上下文 —— 增加了对话
Conversation (对话)
- 多请求,少会话
- 存在于一个JSF用例的时间长短
@ConversationScoped
促进从瞬时的到长期的:
- Conversation.start()
- Conversation.end();
上下文模型
@SessionScoped
public class Race() {
@Inject @Motocross Motorcycle racer1
....
}
伪域:
-
@Dependent
Servlet域:
-
@RequestScoped
-
@SessionScoped
-
@ApplicationScoped
JSF域
-
@ConversationScoped
对话域
@ConversationScoped
public class RentCar {
@Inject Conversation conversation;
public void rentCar(){
CODE TO RENT CAR
conversation.begin();
} ...
类型安全的依赖注入
-
注入现在是基于类型
分类
基于下面的组合:
- Annotation
- Type
- Type Params
- 消除了基于名字/字符串的注入
近看CDI注入
@Motocross
public class Motorcycle extends Vehicle
implements Bike<Motorized> {
…
}
4个方法,这个Bean可以被注入:
-
Motorcycle
-
Vehicle
-
Wheel<TwoWheel>
-
@Motocross
限定者(Qualifiers)
@Motocross是一个限定者( Qualifier):当你有实现了相同接口的多个Bean时,这是一个区分它们的方法。充当一个绑定类型。
@Motocross
public class Motorcycle extends Vehicle
implements Bike<Motorized> {
…
}
@Qualifier@Retention(RUNTIME)@Target ({TYPE, METHOD, FIELD})public @interface Motocross { }
@Alternative
可选择性(Alternatives)作为一个布置时覆盖必须专门启用。然后它们占据了匹配的类型的位置。
@Alternative @Motocross
public class TestBike extends Vehicle
implements Bike<Motorized> {
…
}
由beans.xml
启用:
<alternatives><class>org.jbossmotors.mock.TestBike</class></alternatives>
生产者(Producers)
生产者方法( Producer method)是一个方法,它充当Bean实例的资源。该方法的声明自身描述了Bean,并且当指定的上下文中不存在实例时,容器会调用该方法获取此Bean的一个实例。
@ApplicationScopedpublic class RandomNumberGenerator {private Random random =new Random(System.currentTimeMillis());@Produces @Named @Random int getRandomNumber() {return random.nextInt(100);}}
被用来,在运行时,动态地实现一个注入。
生产者字段(Producer fields)是一个更简单的可选方法。用于JEE组件参考注入特别好。
@Produces @WebServiceRef
(lookup="java:app/service/Catalog") Catalog catalog;
事件通知
表示生产者与观察者完全解耦的一种方式,反之也然。
生产者: DeliveryTracking.java
@Inject Event<Package> delivered;
public void delivery(String recipient) {
delivered.fire(new Package(recipient, timeStamp) );
}
接受者: DeliveryNotifier.java
void onDelivery(@Observes Package package,
@Default Recipient recipient) {
System.out.println(recipient +
“ recieved “ + package.getContents());
统一的确EL集成
- 统一的EL暴露管理的Beans给JSF和JSP视图。
- 所有需要的一切是 @Named注释。
- 大多数资源是可注入的:
- 管理的Beans
- 网页服务参考
- 本地或远程EJBs
- 生产者创建的对象
- 等等
- CDI参考实现。
- “普通(Vanilla)” CDI
- CDI实现是在JBoss AS 6 和GlassFish 3 中。
- 但是也支持Tomcat和Jetty,甚至也支持JavaSE
- 被maven化。
- 提供扩展的基础。
- Weld 扩展是用于扩展核心。
接下来都会去什么地方?—— Seam 3
- 现在,Seam在核心利用CDI被模块化。
- 模块有一个独立发行的周期。
- 普通的快照/包装发行。
- Seam堆栈由以下内容构成:
- Java EE集成在平台内部。
- 声明性安全。
- 页面流(jPDL)和业务流程(jBPM)。
- JavaScrip远程处理。
- “渲染” e-mail, 图形, PDF, 和 XLS
- Spring集成,等等。
- 工具化。
从Seam 2 到 Seam 3
- Seam 3 = Java EE的可移动扩展。
- 构建在CDI 基础的顶部。
- 现在以模块方式组织。
Seam 3 vs. Seam 2
- 已改变的注释。
- @In 现在为 @Inject, @Name 现在为 @Named。
- @ScopeType 由域注释替换 —— @RequestScope 。
- @Begin/@End 调用对话接口,现在为了—— Conversation.begin() 。
- 一些概念/实现被取代。
- Outjection(注出)—— 不是注出某些东西到域内部,而是确保你正在从该域中读取。
- 此外,可使用更安全的生产者字段(Producer Fields)替代。
- 工厂(Factories) —— 来自生产者方法的更安全的结果。
- Outjection(注出)—— 不是注出某些东西到域内部,而是确保你正在从该域中读取。
最新的信息
- http://www.seamframework.org
- 下载
- 文档
- 论坛和社区
- 投稿
小结
- JSR-299 —— 引入了一个灵活的JEE 服务集合:
- 强壮类型的管理的Beans。
- 上下文。
- 动态的依赖注入。
- 多渠道的松耦合。
- 可扩展的SPI。
- Weld是 CDI的参考实现,并且在JBoss 6 和 GlassFish3 中被实现。
- 可以被添加到Tomcat, Jetty。
- Seam 3 —— JEE的可移动扩展(通过CDI)