闲人野居
好好学习,天天向上
posts - 57,  comments - 137,  trackbacks - 0
        日志,是每个系统都不可缺少的。但是,又不是必要的业务需求。
        但用于日志记录的代码和主要用于其它职责的代码缠绕在一起。根据所解决的问题的复杂程度和作用域的不同,所引起的混乱可大可小。更改一个应用程序的日志记录策略可能涉及数百次编辑 ― 即使可行,这是个令人头疼的任务。
         考虑一下以下代码:
清单 1. 日志调用手工插入到每个方法中        
public void doGet(JspImplicitObjects theObjects) throws ServletException
{
  logger.entry("doGet(...)");

  JspTestController controller = new JspTestController();
  controller.handleRequest(theObjects);

  logger.exit("doGet");
}
        可能在不同的方法中都存在这样的代码。这就造成代码的无限扩张,同时修改也变得非常困难。
       使用aop后,更改的代码为:
清单 2. 自动应用于每个方法的记录日志调用
public aspect AutoLog{
  
  pointcut publicMethods() : execution(public * org.apache.cactus..*(..));

  pointcut logObjectCalls() :
    execution(* Logger.*(..));
    
  pointcut loggableCalls() : publicMethods() && ! logObjectCalls();
    
  before() : loggableCalls(){
    Logger.entry(thisJoinPoint.getSignature().toString());
  }
    
  after() : loggableCalls(){
    Logger.exit(thisJoinPoint.getSignature().toString());
  }
}

所有的日志维护都集中于AutoLog方面。

Pointcut 和 join point

要理解 Pointcut,必需知道 join point 是什么。join point 表示在程序执行中明确定义的点。AspectJ 中典型的 join point 包括方法调用、对类成员的访问以及异常处理程序块的执行。join point 可以包含其它 join point。例如,一个方法调用可能在它返回之前引起其它方法调用。那么,Pointcut 就是一种语言构造,这种构造根据已定义的标准挑选一组 join point。示例中的第一个 Pointcut 称为 publicMethods ,选择 org.apache.cactus 包中的所有公用(public)方法的执行。 execution 是一个原始的 Pointcut(就象 int 是一种原始的 Java 类型)。它选择与其括号中定义的方法说明匹配的任何方法的执行。方法说明允许包含通配符;示例中的一个方法说明包含了几个通配符。第二个名为 logObjectCalls 的 Pointcut 选择了 Logger 类中的所有方法的执行。第三个 Pointcut loggableCalls ,通过使用 && ! 合并了前两个 Pointcut,这意味着它选择了除 Logger 类中的公用方法以外, org.apache.cactus 中所有的公用方法。(记录 log 方法将导致无限递归。)

Advice

既然 Aspect 已经定义了它应该记录的点,它使用 Advice 来完成实际的日志记录。Advice 是在 join point 之前、之后或周围执行的代码。相对于 Pointcut 来定义 Advice,说类似于“在想要记录的每个方法调用之后运行这些代码”这样的话。因此 Advice 如下:

before() : loggableCalls(){
    Logger.entry(thisJoinPoint.getSignature().toString());
}

Advice 使用 Logger 类,其入口和出口方法类似于下列代码:

public static void entry(String message){
   System.out.println("entering method " + message);
}

在示例中,传递到记录器的 String 是从 thisJoinPoint 派生的,这是一个特殊的反射对象,它允许访问 join point 执行所处的运行时上下文。在 Cactus 实际使用的 Aspect 中,Advice 使用这种对象来检索传递到每个记录的方法调用中的方法参数。当日志记录 Aspect 应用于代码时,方法调用的结果如下:


清单 3. AutoLog Aspect 的输出

entering method: void test.Logging.main(String[])
entering method: void test.Logging.foo()
exiting method: void test.Logging.foo()
exiting method: void test.Logging.main(String[])

posted on 2006-09-09 08:32 布衣郎 阅读(637) 评论(0)  编辑  收藏 所属分类: aop

只有注册用户登录后才能发表评论。


网站导航:
 

<2006年9月>
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567

常用链接

留言簿(12)

随笔分类(59)

随笔档案(57)

blog

java

uml

搜索

  •  

积分与排名

  • 积分 - 355587
  • 排名 - 154

最新评论

阅读排行榜

评论排行榜