创建Manager
本章将向你展示怎样创建能够同DAO层交互并能处理事务的业务Facade。
这部分内容依赖 Part I: 创建DAO.
关于本章
这部分将向你展示怎样创建同第一部分创建的DAO进行交互的Business Façade类(和一个JUnit Test)。
在 AppFuse中,它被称做Manager类。它的主要职责是充当持久层(DAO) 和Web层之间的桥梁。它也用于对表示层和数据库层进行解耦(de-coupling) (如:Swing程序)。Manager也是你放置业务逻辑(business logic)的地方。
让我们从创建一个ManagerTest和Manager开始吧!
内容
· [1] 创建一个ManagerTest,用来执行 Junit测试Manager
· [2] 创建一个调用DAO的Manager
· [3] 为Manager和Transactions配置Spring
· [4] 运行ManagerTest
创建一个ManagerTest,用来执行 Junit测试Manager
在第一部分,我们创建了一个Person对象和PersonDAO接口 – 我们这里将继续开发这个例子。首先,我们为PersonManager创建一个JUnit test。在test/service/**/service 目录中创建PersonManagerTest。我们想测试和DAO中一样的基本方法 (get, save, remove)。
这个类应该继承在servic包中已经存在的 BaseManagerTestCase ,父类(BaseManagerTestCase) 提供了和BaseDAOTestCase一样的功能 – 装载一个和你的*Test.class 同名的属性文件,同样也初始化Spring的ApplicationContext。
我常常复制 (打开 → 另存为)一个已经存在的测试 (如:UserManagerTest.java) ,然后 使用[Pp]erson查找/替换[Uu]ser。
下面的代码是我们的Manager需要的一个基本的Junit测试。这段代码将简单地创建、销毁PersonManager。"ctx" 对象是被 BaseManagerTestCase 初始化的。
package org.appfuse.service;
import org.appfuse.model.Person;
import org.springframework.dao.DataAccessException;
public class PersonManagerTest extends BaseManagerTestCase {
private Person person = null;
private PersonManager mgr = null;
protected void setUp() throws Exception {
super.setUp();
mgr = (PersonManager) ctx.getBean("personManager");
}
protected void tearDown() throws Exception {
super.tearDown();
mgr = null;
}
}
现在我们有了这个类的Junit测试框架,现在要添加内容: 确保Manager中的一切都正常运转的测试方法。这里有一个片断(snippet),它可以帮助你理解我们将要做什么。
..我们创建以"test"(全部小写)开头的方法. 这些方法是public, 返回void,没有参数。它们将被Ant build.xml文件的<junit>任务调用。这里是一些测试 CRUD的简单测试。需要牢记的是:每个方法都是自治的(autonomous)[就是每个方法都要自己获得Person].
在你的PersonManagerTest.java文件中添加下面的方法:
public void testGetPerson() throws Exception {
person = mgr.getPerson("1");
assertNotNull(person.getFirstName());
}
public void testSavePerson() throws Exception {
person = mgr.getPerson("1");
person.setFirstName("test");
mgr.savePerson(person);
assertEquals(person.getFirstName(), "test");
}
public void testAddAndRemovePerson() throws Exception {
person = new Person();
person = (Person) populate(person);
mgr.savePerson(person);
assertEquals(person.getFirstName(), "Bill");
assertNotNull(person.getId());
log.debug("removing person, personId: " + person.getId());
mgr.removePerson(person.getId().toString());
try {
person = mgr.getPerson(person.getId().toString());
fail("Person found in database");
} catch (DataAccessException dae) {
log.debug("Expected exception: " + dae.getMessage());
assertNotNull(dae);
}
}
此时,这个类不会编译成功,因为我们没有创建PersonManager接口。
为了使AppFuse框架的扩展性更强,我运用了许多设计模式,这很有趣。实际上,我在一年内学到了很多,以至于对于我以前参与的很多工程,我都不想再去扩展它们的架构了-我想重写一遍!
幸运的是,运用我的洞察力和经验,可以使AppFuse能够跟的上潮流,但不幸的是:我每年只能升级,而不能重写。;-)
创建一个调用DAO的Manager
我们将在src/service/**/service 目录中创建PersonManager.java接口,然后为实现这个接口的类指定CRUD方法。I've eliminated the JavaDocs in the class below for display purposes.
我通常复制[duplicate] (open → save as)一个已经存在的文件 (如:UserManager.java)。
package org.appfuse.service;
import org.appfuse.model.Person;
public interface PersonManager {
public Person getPerson(String id);
public void savePerson(Person person);
public void removePerson(String id);
}
现在让我们创建PersonManagerImpl类,它要实现接口PersonManager的方法。为了达到这个目的,我们在目录src/service/**/service/impl中创建一个新类PersonManagerImpl.java。它继承了BaseManager,并且实现PersonManager接口。
package org.appfuse.service.impl;
import org.appfuse.model.Person;
import org.appfuse.dao.PersonDAO;
import org.appfuse.service.PersonManager;
public class PersonManagerImpl extends BaseManager implements PersonManager {
private PersonDAO dao;
public void setPersonDAO(PersonDAO dao) {
this.dao = dao;
}
public Person getPerson(String id) {
return dao.getPerson(Long.valueOf(id));
}
public Person savePerson(Person person) {
dao.savePerson(person);
}
public void removePerson(String id) {
dao.removePerson(Long.valueOf(id));
}
}
需要注意的是setPersonDAO方法。为了使用Spring绑定PersonDAO到这个Manager,我们要配置applicationContext-service.xml文件。我们将在下面配置。现在运行"ant compile-service",你应该可以编译所有的东西了……
最终,我们要在目录test/service/**/service中创建PersonManagerTest.properties文件。这样person = (Person) populate(person);将会为我们的测试工作。
如果你已经在上面创建了PersonDAOTest.properties文件,那么复制,然后重命名是一个很好的办法。当然你也可以手工设置这些属性。
firstName=Bill
lastName=Joy
现在我们需要修改Spring的配置文件,让它知道我们的这个新的Manager。
为Manager和Transactions配置Spring
通知Spring,使它知道PersonManager接口和它的实现类。打开文件src/service/**/service/applicationContext-service.xml。这里,你应该可以看到为 "personManager" bean定义的注释。取消注释,或者添加如下内容到这个文件中:
<bean id="personManager" parent="txProxyTemplate">
<property name="target">
<bean class="org.appfuse.service.impl.PersonManagerImpl" autowire="byName"/>
</property>
</bean>
"parent" 属性涉及到一个Bean的定义 TransactionProxyFactoryBean (它拥有所有的基本事务属性集)
运行ManagerTest
保存所有修改过的文件,然后运行ant test-service -Dtestcase=PersonManager。
Yeah Baby, Yeah:
BUILD SUCCESSFUL
Total time: 9 seconds
The files that were modified and added to this point are available for download .
下一步: Part III: 创建Action和JSP – 讲述怎样创建Action和JSP.