与 EJB 2.1 相比,EJB 3.1 简化了创建 Enterprise Java™ Bean 应用程序的过程。
EJB 2.x 和 J2EE 1.4 体系结构的复杂性
业务层 在 J2EE 1.4 体系结构中,会话 Bean 用于合并业务逻辑组件,从而向它们提供事务性服务、分布式服务、远程服务和安全服务。它们通常实现一种外观模式,以减少客户机与服务供应商之间的网络流量。
会话 Bean 可由本地客户机(表示客户机位于同一 JVM 内)或远程客户机进行访问。
消息驱动的 Bean 用于集成外部 JMS 提供程序(例如 MQSeries)以启用异步消息处理服务。
会话 Bean 和消息驱动的 Bean 一起构成业务逻辑层。
将它们称为层,是因为此企业体系结构设计中所采用的另一个基本范例正在进行分层,这会启用核心功能(例如职责分离和技能)、集群和组件复用。
持久性层 另一个基本层是持久性层,它是一组服务和组件,用于允许将应用程序数据持久存储在关系数据库中。
持久性层通过以下方式实现:
- 实体 Bean(容器管理的 Bean 和 Bean 管理的 Bean)
- JDBC™ 数据访问对象 (DAO)
- 对象关系映射 (ORM) 框架
EJB 2.x 规范的问题
- EJB 2.x 规范组件接口必须扩展 EJB 框架软件包中的某个接口,并且业务逻辑实现类必须实现 EJB 框架软件包中的某个接口。这些需求会在开发人员编写的代码与 EJB 框架软件包的接口类之间创建紧密耦合。它还需要实现未直接与 EJB 的主要设计目标相关的几个不必要回调方法(ejbCreate、ejbPassivate 和 ejbActivate)以及处理不必要异常。
- EJB 部署描述符过于冗长、复杂且容易出错。
- 很难测试 EJB,因为应用程序需要 J2EE 容器提供正确运行 EJB 组件所需的所有服务。
- 每次您必须访问资源(例如数据源或 EJB Home 引用)时对 JNDI 的依赖是 J2EE 开发的重复且乏味的操作。
- 容器管理的持久性模型的开发非常复杂且不易于管理。
EJB 3.1 中简化的模型
Java EE 和 EJB 3.1 的总体体系结构体现了 EJB 3.1 模型的简化:
EJB
3.1 规范的底层概念包含无格式普通 Java 对象 (POJO) 编程模型,该编程模型使用 Java 注释来捕获部署描述符用于包含的信息。
现在,部署描述符在大多数情况下是可选的。如果您大量使用缺省值,那么意味着您需要编写和维护很少的支持代码。这极大地简化了在创建和使用 EJB 3.1 组件时的编程体验。此简化模型的主要功能包括
- 现在,EJB 是用于公开常规业务接口 (POJI) 的无格式普通 Java 对象 (POJO),并且不需要 Home 接口。
- 元数据注释的使用,该元数据注释是用于生成 Java 代码或 XML 部署描述符的可扩展、元数据驱动且面向属性的框架。
- 移除对特定接口和部署描述符的需求(部署描述符信息可替换为注释)。
- 拦截器工具,用于在业务方法的调用或生命周期事件时调用用户方法。
- 尽量使用缺省值(“按异常进行配置”方法)。
- 减少对使用已校验的异常的需求。
- 全新的持久性模型(基于 JPA 标准),用于替换 EJB 2.x 实体 Bean
表 1. 在 EJB
2.1 和 EJB 3.1 中创建 Bean 的步骤比较. EJB 2.x 使用部署描述符,而 EJB 3.1 则使用注释。用于在 EJB 2.x 中定义无状态会话 Bean 的步骤 |
用于在 EJB 3.1 中定义无状态会话 Bean 的步骤 |
要按照 EJB 2.x 规范来创建无状态会话 Bean,请定义下列组件:
- EJB 组件接口:供 EJB 客户机使用,以获取对 Bean 的功能的访问权限。这是用于定义业务方法的位置。该组件接口称为 EJB 对象。
组件接口的类型有两种:
- 远程组件接口 (EJBObject):供远程客户机使用,以通过 RMI-IIOP 协议访问 EJB。
- 本地组件接口 (EJBLocalObject):供运行在同一 JVM 内的本地客户机使用,以访问 EJB。
- EJB Home 接口:供 EJB 客户机使用,以访问 Bean。包含创建、查找或移除的 Bean 生命周期方法。该 Home 接口称为 EJB Home。EJBHome 对象是一个用于实现 Home 接口的对象,在 EJBObject 中于部署期间从容器工具生成,并且包括特定于容器的代码。启动时,EJB 容器会实例化已部署的企业 Bean 的 EJBHome 主对象,并在命名服务中注册该 Home。EJB 客户机使用 Java 命名和目录接口 (JNDI) 来访问 EJBHome 对象。Home 接口的类型有两种:
- 远程 Home 接口 (EJBHome):供远程客户机使用,以通过 RMI-IIOP 协议访问 EJB。
- 本地 Home 接口 (EJBLocalHome):供运行在同一 JVM 内的本地客户机使用,以访问 EJB。
- EJB Bean 类:包含所有实际的 Bean 业务逻辑。
这是用于提供业务逻辑实现的类。此 Bean 类中的方法与组件和 Home 接口中的方法相关联。
|
要按照 EJB 3.1 规范来声明无状态会话 Bean,只需定义 POJO:
@Stateless
public class MySessionBean implements MyBusinessInterface {
// business methods according to MyBusinessInterface
.....
}
- 要在远程接口上公开相同 Bean,请使用 @Remote 注释:
@Remote(MyRemoteBusinessInterface.class)
@Stateless
public class MyBean implements MyRemoteBusinessInterface {
// ejb methods
.....
}
|
EJB 2.1 类加上部署描述符文件与等效的 EJB 3.1 类的比较
表 1 中的各个示例在功能上相当:
表 2. EJB 2.1 和 EJB 3.1 的比较. EJB 2.1 使用部署描述符,而 EJB 3.1 则使用注释。EJB 2.1 |
EJB 3.1 |
Java 类
public class AccountBean
implements javax.ejb.SessionBean {
SessionContext ctx;
DataSource accountDB;
public void setSessionContext(SessionContext ctx) {
this.ctx = ctx;
}
public void ejbCreate() {
accountDB = (DataSource)ctx.lookup(
"jdbc/accountDB");
}
public void ejbActivate() { }
public void ejbPassivate() { }
public void ejbRemove() { }
public void setAccountDeposit(int empId,
double deposit) {
...
Connection conn = accountDB.getConnection();
...
}
...
}
|
Java 类
@Stateless
public class AccountBean implements Account
{
@Resource private DataSource accountDB;
public void setAccountDeposit(int customerId,
double deposit) {
...
Connection conn = accountDB.getConnection();
...
}
...
}
|
部署描述符
<session>
<ejb-name>AccountBean</ejb-name>
<local-home>AccountHome</local-home>
<local>Account</local>
<ejb-class>com.example.AccountBean</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
<resource-ref>
<res-ref-name>jdbc/accountDB</res-ref-name>
<res-ref-type>javax.sql.DataSource</res-ref-type>
<res-auth>Container</res-auth> </resource-ref>
</session>
...
<assembly-descriptor>...</assembly-descriptor>
|
|