恋风的Blog: AspectJ如何实现AOP

AspectJ如何实现AOP

使用AspectJ,我们不用对原有的代码做任何修改,就可以为代码提供不同的Aspect(方面)--比如,认证,事务等。我们只需要提供两个不同的Aspect--认证Aspect和事务Aspect。

比如,我们有一个Bank(银行)类。Bank有两个方法,deposit(存钱)和withdraw(取钱)。
  
 class Bank {

  public float deposit(AccountInfo account, float money){
   // 增加account账户的钱数,返回账户里当前的钱数
  }
  
   public float withdraw(AccountInfo account, float money){
   // 减少account账户的钱数,返回取出的钱数
   }
 }

这两个方法涉及到用户的账户资金等重要信息,必须要非常小心,所以编写完上面的商业逻辑之后,项目负责人又提出了新的要求--给Bank类的每个重要方法加上安全认证特性。
  
于是,我们不得不分别在上面的两个方法中加入安全认证的代码。
  
  class Bank {

   public float deposit(AccountInfo account, float money){
    // 验证account是否为合法用户
    // 增加account账户的钱数,返回账户里当前的钱数
   }
  
   public float withdraw(AccountInfo account, float money){
    // 验证account是否为合法用户
    // 减少account账户的钱数,返回取出的钱数
   }
  }
  
这两个方法都需要操作数据库,为了保持数据完整性,项目负责人又提出了新的要求--给Bank类的每个操作数据库的方法加上事务控制。
  
  于是,我们不得不分别在上面的两个方法中加入安全认证的代码。
  
  class Bank {

   public float deposit(AccountInfo account, float money){
    // 验证account是否为合法用户
    // Begin Transaction
    // 增加account账户的钱数,返回账户里当前的钱数
    // End Transaction
   }
  
   public float withdraw(AccountInfo account, float money){
    // 验证account是否为合法用户
    // Begin Transaction
    // 减少account账户的钱数,返回取出的钱数
    // End Transaction
   }
  }
  
我们看到,这些与商业逻辑无关的重复代码遍布在整个程序中。实际的工程项目中涉及到的类和函数,远远不止两个。如何解决这种问题?
  
我们首先来看看OOP能否解决这个问题。
  
我们利用Design Pattern的Template Pattern,可以抽出一个框架,改变上面的例子的整个设计结构。
  
  abstract class Base {
   public float importantMethod(AccountInfo account, float money){
    // 验证account是否为合法用户
    // Begin Transaction
    float result = yourBusiness(account, money)
    // End Transaction
    return result;
   }
  
   protected abstract float yourBusiness(AccountInfo account, float money);
  }
  
  
  class BankDeposit extends Base{
   protected float yourBusiness(AccountInfo account, float money){
    // 增加account账户的钱数,返回账户里当前的钱数
   }
  };
  
  class BankWithdraw extends Base{
   protected float yourBusiness(AccountInfo account, float money){
    // 减少account账户的钱数,返回取出的钱数
   }
  };
  
这里我们用一种很勉强的方法实现了认证和事务代码的重用。而且,有心的读者可能会注意到,这种方法的前提是,强制所有的方法都遵守同样的signature。
  
如果有一个转账方法transfer(AccountInfo giver, AccountInfo receiver, float money),由于transfer方法的signature不同于yourBusiness的signature,这个方法无法使用上面的框架。
  
这个例子中提到的认证,事务等方面,就是AOP所关心的Aspect。
  
AOP就是为了解决这种问题而出现的。AOP的目的就是-- Separation of Concerns.
  
下面介绍AspectJ工具如何解决Separation of Aspects的问题。

我们只需要提供两个不同的Aspect--认证Aspect和事务Aspect。
 
  aspect AuthAspect {

   pointcut bankMethods() : execution (* Bank.deposit(…)) || execution (* Bank. withdraw (…));

   Object around(): bankMethods(){
    // 验证account是否为合法用户
    return proceed();
   }
  }

  aspect TransactionAspect {

   pointcut bankMethods() : execution(* Bank.deposit(…)) || execution (* Bank. withdraw (…));
  
   Object around(): bankMethods(){
    // Begin Transaction
    Object result = proceed();
    // End Transaction
    return result;
   }
  }
  
我们用AspectJ编译器编译Bank文件和含有aspect的这个文件,出来的结果就是带有安全认证和事务处理的Bank类。编译出来的这个Bank类调用了AspectJ Runtime Lib,所以,如果你要运行这个Bank类,你需要把AspectJ Runtime Lib设置在你的classpath里面。
  
我们来看看,AspectJ编译器为我们做了什么事情。
1. 首先,AspectJ从文件列表里取出所有的文件名,然后读取这些文件,进行分析。
2. AspectJ发现一些文件含有aspect的定义,在这个例子里,就是AuthAspect和TransactionAspect的定义;这些aspect就是代码生成规则。
3. AspectJ根据这些aspect代码生成规则,修改添加你的源代码。在这个例子里,就是修改添加Bank文件。
4. AspectJ读取AuthAspect的定义,发现了一个pointcut--bankMethods();这个pointcut的定义是execution(* Bank.deposit(…)) || execution(* Bank. withdraw (…)),表示所有对Bank类的deposit和withdraw方法的执行点。
5. AspectJ继续读取AuthAspect的定义,发现了一个around(),这在AspectJ中叫做Advice, Advice允许你在某个类的方法的调用之前或调用之后,加入另外的代码。所示代码中的around()的" // 验证account是否为合法用户"部分,就是要加入的代码。这段代码要加在哪里呢?around()后面跟了一个pointcut--bankMethods()。根据这个pointcut,AspectJ会把这段代码加入到Bank.deposit和Bank.withdraw两个方法的执行之前。
6. AspectJ读取TransactionAspect的定义,象第(4)步一样,发现了发现了一个pointcut--bankMethods()。
AspectJ继续读取AuthAspect的定义,发现了一个around()。这次AspectJ把"Begin Transaction"和"End Transaction"两段代码加在Bank.deposit和Bank. withdraw两个方法的执行前后。

本文转自
http://www.360doc.com/showWeb/0/0/170235.aspx

你可能感兴趣的:(JSP框架类)