日志,是每个系统都不可缺少的。但是,又不是必要的业务需求。
但用于日志记录的代码和主要用于其它职责的代码缠绕在一起。根据所解决的问题的复杂程度和作用域的不同,所引起的混乱可大可小。更改一个应用程序的日志记录策略可能涉及数百次编辑 ― 即使可行,这是个令人头疼的任务。
考虑一下以下代码:
清单 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 类型)。它选择与其括号中定义的方法说明匹配的任何方法的执行。方法说明允许包含通配符;示例中的一个方法说明包含了几个通配符。第二个名为