本文章转自http://blog.sina.com.cn/s/blog_538706ce010006vt.html
感谢原作者的分享!
————————————————————————————————————————————————————————————————————
Spring中乃有5中通知:前置通知、后置通知、包围通知、抛出通知和引入。
经验表明,以上五种通知和方法调用连接点可以完成90%的AOP工作,对于剩下不常用的10%,可使用AspectJ来完成。
通常,我们有两种方法将一个通知加到代理中去:
1。直接使用addAdvice()方法
2。使用addAdvisor()方法和Advisor类。
不过现在,通常都是用前者。因为Spring AOP采用了AOP联盟的接口,所以,新版本的Spring中,通知都是接口继承。通过使用addAdvice()将会比后者更加方便。
关于Spring不同的通知接口,其UML参见下图。
创建前置通知
作用:可以修改传递给目标方法的参数,也可以抛出一个异常来阻止目标执行。
实现:前置通知MethodBeforeAdvice接口仅仅定义了一个方法before()。
方法签名:
before(Method method, Object[] args, Object target)
Method 参数代表了被调用的方法,Object[]参数代表了传递给这个被调用方法的参数,最后一个Object参数则指明了要把Method和参数传递给的目标对象。
例程代码:
(P150,代码清单 6-4,SimpleBeforeAdvice类,部分)
public class SimpleBeforeAdvice implements MethodBeforeAdvice {
}
输入如下:
Before Method: writeMessage
World
首先,被通知的类依然采用了上节中的MessageWriter类。之后,我们首先调用了writeMessage()方法,之后不出所料,在writeMessgage方法被调用之前拦截到了它的调用,并且输出了被调用方法的方法名。其次,被调用方法再输出自己的内容。
通过这个实例不难看出,如果有必要,不仅可以通过修改Object[]数组中的值来达到修改方法参数的目的,同时,可以通过修改target来达到对象操作的功能。
实际应用:
当用户登录的时候,可以考察用户的登录信息,对于合法信息,放行并接受数据库的验证,对于非法信息,阻挡并抛出异常。
原书中给提供了一个如何通过前置通知来管理方法调用安全性的程序,欢迎大家阅读原书以获取更详细的信息。此处进给出程序的大概思路。
考虑有如下程序,类A负责登录,有一个名为logon的方法,类B负责实现前置通知。当类A调用logon方法时,被类B负责拦截,检查登录用户名是否为合法用户,合法则允许登录,不合法则抛出异常。
创建后置通知
作用:在方法调用结束后执行后置通知,做一些善后工作。
限制:
- 不能修改方法调用连接点的参数
- 只等读取,而不能修改目标方法的执行路径或者让目标方法不执行
- 不能修改方法的返回值,但是可以抛出异常,使得调用方法只能看到这个异常而非返回值
实现:后置通知AfterReturningAdvice仅仅定义了一个方法,afterReturing().
方法签名
afterReturning(Object returnValue, Method method, Object[] args, Object target)
四个参数依次是:目标方法调用的返回值、目标方法的引用、目标方法参数和目标对象。
例程代码:
(P156, Listing 6-10,SimpleAfterReturningAdvi
public class SimpleAfterReturning implements AfterReturningAdvice {
}
输出如下:
World
After method: writeMessage
跟预想的一样,后置通知是在方法调用结束用运行,所以首先输出的是World,之后输出的才是方法调用中的内容。
实际应用:
一般用于对可能返回无效值的方法的返回值进行进一步的出错检查。
原书中所举的例子是说,某个密钥对于某些加密算法可能是个弱密钥,但是通常密钥生成器不会检查这一点,而且生成弱密钥的几率也非常低,但是可以使用后置通知来进一步检查弱密钥。(《开发指南》上说真正的密钥生成器可能要很多年才会生成一个弱密钥)
这里仅给出实现AOP AfterReturningAdvice逻辑的部分,代码如下:
afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
}
这个方法实现的非常有特色。首先target的运用,是一个很好的例子。KeyGenerator是我们自定义的类,用来生成密钥的,它有三分之一的几率生成弱密钥。程序首先检查,出现方法调用的对象是否是KeyGenerator,之后再检查方法调用的是否是getKey方法(KeyGenerator的方法,返回一个密钥)。如果返回的密钥是个弱密钥,就抛出异常。
之后,用一个使用AOP的主程序,它负责不停的用KeyGenerator生成密钥,如果生成了弱密钥,会被后置通知检测到,从而给这个主程序抛出一个异常,这样,主程序针对异常进行处理。这样就完成通过后置通知检测方法返回值的工作。