面向切面(AOP)与面向对象(OOP)(2) try { businessUnitFile = new FileReader(FILE_NAME); bufferedBusinessUnitFile = new BufferedReader(businessUnitFile); String businessUnitRecord; while((businessUnitRecord = bufferedBusinessUnitFile.readLine()) != null) { BusinessUnit businessUnit = BusinessUnitFactory.createBusinessUnit(businessUnitRecord); businessUnits.add(businessUnit); } } finally { if(bufferedBusinessUnitFile != null) { bufferedBusinessUnitFile.close(); } if(businessUnitFile != null) { businessUnitFile.close(); } } } catch(IOException ioe) { String message = &IOError. Unable to find Business Unit records&; logger.log(SEVERE, message, ioe); throw new RepositoryException(message, ioe); } logger.log(INFO, &Manager Records returned:& + businessUnits.size()); return businessUnits; } 上面的代码通过FileReader和BUfferedReader来读取CSV文件中的业务数据. 应用程序重复地从资源文件中取得数据然后在操作完成后释放.我们会发现:去掉程序的这两个&切面&将提高代码的可读性并达到一个更好的设计,因为去掉这些&多余&的东西,剩下的代码才是这个方法真正的精髓.这个方法的作用是读取业务单位数据.所以不应该也不需要去知道&如何获取和释放资源以及这个过程中出现的异常&这个&切面&.同样地,使用AOP处理异常也变得不同.(后面将详细介绍) 持久层 传统的OOP使用仓库类(repository classes)来打理应用程序的持久层.即: public class EmployeeRepository { public static void createEmployee(Employee employee) throws RepositoryException { //使用print writer把数据放入csv文件 } public static String findEmployeeRecordById(String id) throws RepositoryException { //使用file reader来获得指定id的员工数据 } public static Employee findEmployeeById(String id) throws RepositoryException { //使用该方法获取员工数据,Employee对象由工厂类创建 } public static void updateEmployee(Employee employee) { //更新员工数据 } } 类EmployeeService 使用一个仓库类给应用中相关雇员提供服务,在一个企业应用中,从域模型(domain model)中去掉持久层代码是一种设计上的改进.模型设计者和程序员就可以关注各自的业务逻辑和持久层处理.后面你将会看到如何通过AOP来达到这样的效果. 日志 删除用于调试的日志代码将会极大地改进代码的可读性.考虑下面的代码片断: public Employee createEmployee(String name, String contactNumber, BusinessUnit businessUnit,
Manager manager)
throws EmployeeServiceException {
String id = createNewEmployeeId();
Employee employee =
EmployeeFactory.createEmployee(id, name, contactNumber, businessUnit, manager);
try {
EmployeeRepository.createEmployee(employee);
} catch(RepositoryException re) {
String message = &Created employee successfully:& + employee;
logger.log(SEVERE, message);
throw new EmployeeServiceException(message, re);
}
logger.log(INFO, &Created employee successfully:& + employee);
return employee;
}
上面的代码里包含了一个致命错误和一个成功信息.输出日志这一&切面&同样可以移到业务模型外独立实现.
异常处理
异常处理的例子我这里不再赘述,但这节已经通过上面的代码讨论了潜在的问题.当你调用EmployeeRepository 对象的createEmployee 方法时,你可能会得到一个RepositoryException异常.传统的解决方法是,在这个类中处理.另一种方法是,当RepositoryException 异常被抛出时createEmployee 方法返回null,catch块中的其他逻辑可以在类外处理这一错误.
错误处理在不同的情况中也会不同.但是,通过AOP可以区分开每种情况.
图3
图3中描述了AOP方法的设计以及在一个更抽象的层次上类间的交互.你可以通过对比图1和图3来更好地理解AOP.
程序的目的是通过BusinessUnit对象读取CSV文件中的记录然后 填入类BusinessUnitService 中的map.使用AOP来填充这个map有点类似后门(backdoor)方法 -- 控制被委派给BusinessUnit 来读取存储介质中的记录.
AOP就是定义一些切入点(pointcut)和处理方法(advice).一个&切入点&是源代码中一个执行点.前面的例子定义了一个&切入点& -- 类BusinessUnitService中的findBusinessUnits方法.一个&处理方法&顾名思义就是当执行到某个&切入点&时的一块代码.类BusinessUnitPersistentAspect 包括advice方法findAllBusinessUnits,该方法从存储介质中载入数据,然后使用工厂类创建BusinessUnit 对象.然后这个对象被加入map,map对象的引用通过BusinessUnitService 对象获得.&切入点&和&处理方法&组成了所谓的&切面(Aspect)&
为了读取存储介质中的数据,OOP方法通过一个DAO类来做.而AOP中,你只要定义一个&切入点&和相应的&处理方法&来读取数据.AOP框架会以advice的形式注入代码,既可以在执行期也可以在编译期.
总而言之,当类BusinessUnitService 中的findAllBusinessUnits 方法被调用时,AOP框架会在&切入点&处注入处理方法,通过BusinessUnit 对象预先读取数据来填充map对象.这样,持久层方面的代码就可以移到业务代码之外了.
本文来自联城技术网(http://www./)转发请保留地址:http://www./SE/Uml/20090711_7272_3.html
面向切面(AOP)与面向对象(OOP)(4)
新方法里的&切面&
本节讨论如何用AOP为应用程序的各个&切面&建模
操作资源
类BusinessUnitPersistenceAspect 的持久方法使用了一个buffered reader.你甚至可以定义&切面&的&切面&,但为了简单,这里只关注类的查找方法.
@Aspect(&perJVM&)
public class BufferedFileReaderAspect {
@Expression(&execution(* org.javatechnocrats.aop.withaop.aspects.Busi
本文来自联城技术网(http://www./)转发请保留地址:http://www./SE/Uml/20090711_7272_4.html
|
|