分享

Spring AOP学习4 - 使用基于Aspectj风格配置AOP-3 配置详解

 紫翰 2012-03-19
1,@AspectJ支持
@AspectJ使用了Java 5的注解,可以将切面声明为普通的Java类。@AspectJ样式在AspectJ 5发布的AspectJ project部分中被引入。Spring 2.0使用了和AspectJ 5一样的注解,并使用AspectJ来做切入点解析和匹配。但是,AOP在运行时仍旧是纯的Spring AOP,并不依赖于AspectJ的编译器或者织入器(weaver)。使用AspectJ的编译器或者织入器的话就可以使用完整的AspectJ语言


2,启用@AspectJ支持
为了在Spring配置中使用@AspectJ切面,你首先必须启用Spring对@AspectJ切面配置的支持,并确保自动代理(autoproxying)的bean是否能被这些切面通知。自动代理是指Spring会判断一个bean是否使用了一个或多个切面通知,并据此自动生成相应的代理以拦截其方法调用,并且确保通知在需要时执行。

通过在你的Spring的配置中引入下列元素来启用Spring对@AspectJ的支持:
<aop:aspectj-autoproxy/>   // 使用的是schema

如果你正在使用DTD,你仍然可以通过在你的application context中添加如下定义来启用@AspectJ支持:
<bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator" />

你需要在你的应用程序的classpath中引入两个AspectJ库:aspectjweaver.jar和aspectjrt.jar。这些库可以在AspectJ的安装包(1.5.1或者之后的版本)的'lib'目录里找到,或者也可以在Spring-with-dependencies发布包的'lib/aspectj'目录下找到。


3,声明一个切面
启用@AspectJ支持后,需要在spring中声明一个带有@Aspect注解的切面类
@Aspect 
public class NotVeryUsefulAspect { 
 }
<bean id="myAspect" class="org.xyz.NotVeryUsefulAspect" />
注:在Spring AOP中,拥有切面的类本身可能是其它切面中通知的目标。一个类上面的@Aspect注解标识它为一个切面,并且从自动代理中排除它。


4,声明一个切入点(pointcut)
切入点决定了连接点关注的内容,使得我们可以控制通知什么时候执行。Spring AOP只支持Spring bean的方法执行连接点。所以你可以把切入点看做是Spring bean上方法执行的匹配。一个切入点声明有两个部分:一个包含名字和任意参数的签名,还有一个切入点表达式,该表达式决定了我们关注那个方法的执行。在@AspectJ注解风格的AOP中,一个切入点签名通过一个普通的方法定义来提供,并且切入点表达式使用@Pointcut注解来表示(作为切入点签名的方法必须返回void 类型)。 

用一个例子能帮我们清楚的区分切入点签名和切入点表达式之间的差别,下面的例子定义了一个切入点'anyOldTransfer',这个切入点将匹配任何名为 "transfer" 的方法的执行:

@Pointcut("execution(* transfer(..))")// the pointcut expression
private void anyOldTransfer() {}// the pointcut signature


5,关联 切面,切入点,通知
打个比方,我要在所有service的save()方法执行加一个日志记录,那么可以这样比喻:
切面:做日志记录的方法logOnSave()
切入点:所有的
service的
save()方法
通知:在save()方法执行前
切面与切入点可以整在一起,也可以分开,各有各的好处,
5.1,切面与切入点分开
/*
* 1,定义切入点
*/
@Aspect
public class LogPointcut{
//com.sun.service包及其子包下所有类的所有save()方法
@Pointcut(value="execution(public * com.sun.service..*.save(..))")  
public void 
logOnSave(){
//无需任何实现,仅仅当作类似一个标记使用
}
}
/*
* 2,定义切面类
*/
@Component  //将当前切面在spring中定义成一个bean
@Aspect
public class LogAspect{

//这里直接指向具体切入点的定义的方法
@Before(value = "com.sun.aop.pointcut.
LogPointcut
.
logOnSave
()")
public void 
logOnSave(){
//实现具体的日志记录
}
}

5.2,切面与切入点整合在一起
/*
* 1,定义切面类
*/
@Component  //将当前切面在spring中定义成一个bean
@Aspect
public class LogAspect{

//这里直接使用AspectJ表达式指定切入点(也就是
所有save()方法
@Before(value = "
execution(public * com.sun.service..*.save(..))
")
public void 
logOnSave(){
//实现具体的日志记录
}
}

总结:
当有多个切面需要使用相同的切入点时,使用5.1的方法比较好,共享切入点后,以后需要修改切入点的定义时,只需要修改一个地方即可。如果你不会共享切入点,那么使用5.2的方式会减少复杂性,具体可在使用时根据情况来选择
上一篇《

使用基于Aspectj风格配置AOP-2 共享通用切入点定义
》就已经用具体实例说明了此问题

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多