Spring3开发实战 之 第三章:AOP开发(2)(五)

2014-11-24 08:36:49 · 作者: · 浏览: 3
)"
method="audit"
arg-names="auditable"/>
Advisor
“advisors”这个概念来自Spring1.2对AOP的支持,在AspectJ中是没有等价的概念。 advisor就像一个小的自包含的切面,这个切面只有一个通知。

java代码:
查看复制到剪贴板打印

expression="execution(* com.xyz.myapp.service.*.*(..))"/>
pointcut-ref="businessService"
advice-ref="tx-advice"/>

Spring AOP还是完全用AspectJ?
优先选用Spring的AOP,因为它不是一个人在战斗,Spring除了AOP,还有IOC,还有事务等其他功能。
如果你需要通知domain对象或其它没有在Spring容器中 管理的任意对象,那么你需要使用AspectJ。
Spring AOP中使用@AspectJ还是XML?
优先使用@AspectJ。
XML风格有两个缺点。第一是它不能完全将需求实现的地方封装到一个位置。DRY原则中说系统中的每一项知识都必须具有单一、无歧义、权威的表示。 当使用XML风格时,如何实现一个需求的知识被分割到支撑类的声明中以及XML配置文件中。当使用@AspectJ风格时就只有一个单独的模块 -切面- 信息被封装了起来。 第二是XML风格同@AspectJ风格所能表达的内容相比有更多的限制:仅仅支持"singleton"切面实例模型,并且不能在XML中组合命名连接点的声明。

Spring AOP使用JDK动态代理或者CGLIB来为目标对象创建代理。如果被代理的目标对象实现了至少一个接口,则会使用JDK动态代理。所有该目标类型实现的接口都将被代理。若该目标对象没有实现任何接口,则创建一个CGLIB代理。
如果你希望强制使用CGLIB代理,(例如:希望代理目标对象的所有方法,而不只是实现自接口的方法)那也可以。但是需要考虑以下问题:
1:无法通知(advise)Final 方法,因为他们不能被覆写。
2:将CGLIB 2二进制发行包放在classpath下面,JDK本身就提供了动态代理
3:强制使用CGLIB代理需要将 的 proxy-target-class 属性设为true:

4:当需要使用CGLIB代理和@AspectJ自动代理支持,请按照如下的方式设置 的 proxy-target-class 属性:

切入点的API
org.springframework.aop.Pointcut 是最核心的接口,用来将 通知应用于特定的类和方法,完整的接口定义如下:

java代码:
查看复制到剪贴板打印
public interface Pointcut {
ClassFilter getClassFilter();
MethodMatcher getMethodMatcher();
}
1:将Pointcut接口分割成有利于重用类和方法匹配的两部分,以及进行更细粒度的操作组合(例如与另一个方法匹配实现进行“或操作”)。
2:ClassFilter接口用来将切入点限定在一个给定的类集合中。如果matches()方法总是返回true,所有目标类都将被匹配:
public interface ClassFilter {
boolean matches(Class clazz);
}
3:MethodMatcher接口通常更重要,完整的接口定义如下:

java代码:
查看复制到剪贴板打印
public interface MethodMatcher {
boolean matches(Method m, Class targetClass);
boolean isRuntime();
boolean matches(Method m, Class targetClass, Object[] args);
}
matches(Method, Class)方法用来测试这个切入点是否匹配目标类的指定方法。这将在AOP代理被创建的时候执行,这样可以避免在每次方法调用的时候都执行。如果matches(Method, Class )对于一个给定的方法返回true,并且isRuntime() 也返回true,那么matches(Method, Class , Object[])将在每个方法调用的时候被调用。这使得切入点在通知将被执行前可以查看传入到方法的参数。

大多数MethodMatcher是静态的,这意味着isRuntime()方法返回 false。在这种情况下,matches(Method, Class , Object[])永远不会被调用。

静态切入点
静态切入点基于方法和目标类进行切入点判断而不考虑方法的参数。在多数情况下,静态切入点是高效的、最好的选择。 Spring只在第一次调用方法时执行静态切入点:以后每次调用这个方法时就不需要再执行。
1:正则表达式切入点
正则表达式是最常用的描述静态切入点的方式,多数AOP框架都支持这种方式。org.springframework.aop.support.Perl5RegexpMethodPointcut是一个最基本的正则表达式切入点, 它使用Perl 5正则表达式语法。示例如下:

java代码:
查看复制到剪贴板打印
class="org.springframework.aop.support.Perl5RegexpMethodPointcut">


.*set.*
.*absquatulate



拦截around通知
Spring里使用方法拦截的around通知兼容AOP联盟接口。实现around通知的MethodInterceptor应当实现下面的接口:

java代码:
查看复制到剪贴板打印
public interface MethodInterceptor extends Interceptor {
Object invoke(MethodInvocation invocation) throws Throwable;
}
提示:在invok方法里面不要忘记调用:invocation.proceed();
前置通知

java代码:
查看复制到剪贴板打印
public interface MethodBeforeAdvice extends BeforeAdvice {
void before(Method m, Object[] args, Object target) throws Throwable;
}
后置通知

java代码:
查看复制到剪贴板打印
public interface AfterReturningAdvice extends Advice {
void afterReturning(Object returnValue, Method m, Object[] args, Object target) throws Throwable;
}
异常通知
如果连接点抛出异常,异常通知(throws advice)将在连接点返回后被调用。 Spring提供类型检查的异常通知,这意味着org.springframework.aop.ThrowsAdvice接口不包含任何方法:它只是一个标