首页 | IT新闻 | 硬件 | 操作系统 | 开发 | 网络编程 | 数据库 | 热门框架 | 网络安全 | 组网 | 建站指南 | 网页制作 | 特效 | 实用技巧 | 服务器 | 办公 | QQ | 探索 | 社区

  • 技术部落
  • 部落首页 > 热门框架 > Spring开源框架 > 正文
  • 浅析Spring 2.X中AOP的使用
      2007-9-4  来源:天极网  编辑:Jsbulo  热度:

    和Spring 1.X相比,Spring 2.X使用AspectJ的语法来声明AOP,这使得它更“标准”,更灵活了。还是那句话,如果你不了解AspectJ并且打算使用Spring2.X的AspectJ式AOP,那就学学AspectJ吧!这方面的书还是很多了。

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

    先介绍第一种配置方式。需要指出的是,Spring 2.X的beans名称空间和Spring 1.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的实用类,这里用它不过输出一些和连接点有关的信息。当然,在Spring 2.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 >

    完成上面的工作相当于完成了Spring 1.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提供的事务注释作用于类文件上,这可是更细粒度的事务声明了。