4. 更易于理解的seam编程模型
现在我们已经大致了解了Hello World的应用。但是我们还有一些重要的话题继续,例如其他折中途径以及前面代码没有涉及到重要特性,我们将在本节讨论这些话题。它们能帮助开发者对seam更深刻的理解,但是如果你没有耐心,可以直接跳过本节,需要的时再来阅读。
4.1 Seam POJO组件
上例中,我们用一个EJB3会话bean实现了应用逻辑,但是我们并不局限于EJB3组件。事实上,Seam中任何一个有@Name注解的POJO都能被转化为一个可管理的组件。
例如,我们能将ManagerAction转化为一个 POJO,而不是一个EJB3 session bean。
@Name("manager") public class ManagerAction { @In (create=true) private EntityManager em; ... ... }
使用POJO取代EJB3 bean有正反两方面意见,使用POJO编程时很简单,因为它们不需要EJB3特有的注解和接口(参见上文)。如果你的所有业务组件都是Seam POJO, 那么你就能不依赖EJB3应用服务器,运行你的Seam 应用(参见23章,没有EJB3的Seam)。
但是,POJO比EJB3的功能少,因为POJO不能获得EJB3容器服务。在不依赖EJB3的Seam 中丧失的EJB3服务就包括以下几点:
- @PersistenceContext注入在POJO中不在管用。为了在一个Seam POJO中得到EntityManager,开发者不得不在Seam配种文件中初始化EntityManager,然后使用Seam注解@In将它注入到POJO中。
- POJOs中将不在支持方法级别事务声明(declarative method-level transaction)。相反,你可以配置Seam来划分事务,可以从收到web请求开始直到响应页面产生结束。
- Seam POJO不是消息驱动组件。
- 不支持注解为@Asynchronous的方法。
- 不支持容器安全管理。
- 没有事务或者组件级别的持久上下文。Seam POJO中的所有的持久上下文都是经过拓展的(更多细节请参见7.1 “默认的对话作用域”)。
- 没有集成容器管理的体系结构(例如,JMX控制台服务)。
- Seam POJO方法中没有Java RMI。
- Seam POJO不能是注解为@WebService组件。
- 没有JCA集成。
所以当在EJB3容器中进行部署时,为什么每个人都想使用POJO组件?答案就是,POJO组件对于纯“业务逻辑”组件非常有益。POJO为其他组件代理了数据访问、消息传递和其他基本功能。例如,我们能使用POJO组件操纵Seam数据访问对象,这对“业务逻辑”POJO是非常有用的,因为它们可以在需要的时候,在其他框架中被重用。但是总的来说,它们的应用要比EJB3组件少,特别是在中小型应用中。所以,本书的大多数例子我们都使用EJB3组件。
4.2 易于测试
我们已经在第一章中提到,Seam为了不依赖容器的方便的测试,进行了重新设计。在helloworld项目中,我们在测试文件夹中包括了单元测试和集成测试这两个测试用例。在纯Java SE环境下,Seam 测试体系模拟了数据库、JSF、Seam上下文以及其他应用服务器服务,只要运行ant test命令就能运行所有的测试。
4.3 基于Getter和Setter的双向映射
在Hello World一例中,我们已经展示了通过成员变量对Seam组件进行的双向映射,你也能通过Getter和Setter方法对组件进行双向映射。例如,以下代码就工作的很好。
private Person person; private List <Person> fans; @In public void setPerson (Person person) { this.person = person; } @Out public Person getPerson () { return person; } @Out public List <Person> getFans () { return fans; }
虽然以上的getter和setter方法看似轻微,利用getter和setter方法的双向映射真正的价值在于能其加入定制逻辑来操纵双向映射的过程。例如,你可以验证被注入的对象或者快速地从数据库重新得到被抛出的对象。