边城愚人

如果我不在边城,我一定是在前往边城的路上。

  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  31 随笔 :: 0 文章 :: 96 评论 :: 0 Trackbacks

        在结束了上一篇Spring 1.x中AOP的使用之后,我又马不停蹄的打开Eclipse,做着Spring2.X下了AOPSample。在上一篇文章中的配置过程中,由于对自动代理不是很熟,出现了循环引用的异常信息。当初在阅读PicoContainer源码时看到循环引用不以为然,后来在学习AspectJ时小有印象,这次在折腾了半个多小时后可加深了印象。

        好啦,闲言少叙,奔向文本的主题吧。和Spring1.X相比,Spring2.X使用AspectJ的语法来声明AOP,这使得它更“标准”,更灵活了。还是那句话,如果你不了解AspectJ并且打算使用Spring2.XAspectJAOP,那就学学AspectJ吧,这方面的书还是很多了。

        Spring2.X下的切面有两种实现方式,一种是以Java文件定义切面(其只是普通的Java类),然后在配置文件中声明定义的切面;另一种是在Java类中引入和AOP相关的元数据(注释)。

        先介绍第一种配置方式。需要指出的是,Spring2.Xbeans名称空间和Spring1.X有所不同,它采用了Schema而不是DTD(也可采用DTD方式,具体的请参考文档)。还是引入毫无意义的日志切面,定义的切面类LogingAspect 如下:


public   class  LogingAspect {

public   void  logMethod(JoinPoint jp){

        System.err.println(jp.getTarget().getClass());

        System.err.println(jp.getSignature().getName());

}

}

        同时在配置文件中如下配置:


< bean id = " logAspectTarget "   class = " hibernatesample.service.util.LogingAspect " ></ bean >

< aop:config >

< aop:aspect id = " logAspect "  ref = " logAspectTarget " >

< aop:pointcut id = " businessService "  expression = " execution(* hibernatesample.service.*.*(..)) " />

< aop:after pointcut - ref = " businessService "  method = " logMethod " />

</ aop:aspect >

</ aop:config >

       对于上面的切面,切入点businessService是在配置文件中声明的,其表达式采用了 AspectJ的语法,LogingAspect 类中logMethod(JoinPoint jp)方法根据配置文件信息可知其是after通知,方法的JoinPoint参数不是必须的,它是来自于AspectJ的实用类,这里用它不过输出一些和连接点有关的信息。当然,在Spring2.X中,切入点和通知能更灵活的使用,我们可以如AspectJ一样传递参数给通知。如果需要在Service中引入事务功能,需要如下配置事务通知:


< tx:advice id = " txAdvice "  transaction - manager = " transactionManager " >

< tx:attributes >

< tx:method name = " get* "  read - only = " true " />

< tx:method name = " find* "  read - only = " true " />

< tx:method name = " * " />

</ tx:attributes >

</ tx:advice >


< aop:config >

< aop:pointcut id = " demoServiceMethods "  expression = " execution(* hibernatesample.service.*.*(..)) " />

< aop:advisor advice - ref = " txAdvice "  pointcut - ref = " demoServiceMethods " />

< aop:aspect id = " logAspect "  ref = " logAspectTarget " >

< aop:pointcut id = " businessService "  expression = " execution(* hibernatesample.service.*.*(..)) " />

< aop:after pointcut - ref = " businessService "  method = " logMethod " />

</ aop:aspect >

</ aop:config >



        完成上面的工作相当于完成了 Spring1.X 自动代理。 我们接下来需要定义的任何 Service Bean 都可以很纯粹很纯粹了:


< bean  id ="accountService"  class ="hibernatesample.service.impl.AccountServiceImpl" >

< property  name ="accountDAO"  ref ="accountDAO" ></ property >

</ bean >


        第二种实现 AOP 的方式和第一种相比,只是在 LogingAspect 中加入了注释,而省去了配置文件中和 LogingAspect 相关的配置。重新编写的 LogingAspect 如下:


@Aspect

public   class  LogingAspect {

@Pointcut(
" execution(* hibernatesample.service.*.*(..)) " )

public   void  businessService(){}

@After(
" businessService() " )

public   void  logMethod(JoinPoint jp){

System.err.println(jp.getTarget().getClass());

System.err.println(jp.getSignature().getName());

}

}

        而简化后的配置文件可以去除上面的如下和 logAspect 相关的配置信息:


< aop:aspect  id ="logAspect"  ref ="logAspectTarget" >

< aop:pointcut  id ="businessService"  expression ="execution(* hibernatesample.service.*.*(..))" />

< aop:after  pointcut-ref ="businessService"  method ="logMethod" />

</ aop:aspect >

< bean  id ="logAspectTarget"  class ="hibernatesample.service.util.LogingAspect" ></ bean >

        还没有完,为了使 Spring 应用 LogingAspect  的注释,需要在配置文件中添上

        <aop:aspectj-autoproxy/>


         如果觉得事务的配置没有使用注释更简洁(我倒不会有这样的想法,毕竟在配置文件中声明的事务只是那么固定的几段,除非作用于类上的事务逻辑上很复杂),也可以使用Spring提供的事务注释作用于类文件上,这可是更细粒度的事务声明了。

      坦率的说,由于时间有限,该文写的比较粗糙。对于Spring AOP有兴趣并有疑问的朋友,可以参考Spring的文档,它的文档做的还是不错的。
posted on 2007-08-30 08:42 kafka0102 阅读(2266) 评论(2)  编辑  收藏 所属分类: FrameworkAOP

评论

# re: Spring2.X中AOP的使用 2007-08-30 12:40 JAVA面试题
学习了  回复  更多评论
  

# re: Spring2.X中AOP的使用 2007-08-30 18:15 光荣之翼
收藏  回复  更多评论
  


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


网站导航: