《Spring AOP学习总结之三—AOP对于事务的配置》

来源:互联网 发布:千牛mac官方版 编辑:程序博客网 时间:2024/05/16 07:38

     关于AOP配置事务这一块,之前都是直接copycode,对其中的道理还不是特别理解。现在在学习AOP源码的过程中,对这一块稍稍有了点想法,现在做一记录与总结。首先声明,这是作为AOP的总结博客,所以重心不是事务怎样怎样,而是对应于AOP后怎样怎样。

       在上一篇博客中,提到,若通过xml配置AOP,需要做三件事,如下:

1·写切面类(日志,异常控制等)

2·在切面类中写通知方法

3·在处理器中添加的切入点(过滤条件)

       同样,即便AOP提供对事务的支持,本质的东西都还是要存在的。所以,下面我们一一进行分析。

       代码:

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"       xmlns:aop="http://www.springframework.org/schema/aop"       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">   <!-- 1、配置一个事务管理器    2、配置tx,使用tx配置的拦截器    3、配置切面-->    <!--1·事务管理器 的作用就是告诉spring容器利用jdbc的技术进行处理,如果是采用的hibernate则需要配置HibernateTransactionManager来实现 -->    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">        <property name="dataSource">            <ref bean="dataSource"/>        </property>    </bean>    <!-- 2· 声明事务策略 id是标示符 transaction-manager 事务管理器 -->    <tx:advice id="tx" transaction-manager="transactionManager">        <tx:attributes>            <!--    告诉spring容器什么样的目标方法采用什么样的事务策略                 name 用来说明目标方法  save*  以save开头的目标方法                 isolation 隔离属性   propagation 传播属性是解决事务嵌套问题的                 read-only为true:只读事务  只能读  为false:读写事务 ??这里需要对事务的属性配置了解一下  -->            <tx:method name="save*" propagation="REQUIRED" />            <tx:method name="insert*" propagation="REQUIRED" />            <tx:method name="add*" propagation="REQUIRED" />            <tx:method name="create*" propagation="REQUIRED" />            <tx:method name="delete*" propagation="REQUIRED" />            <tx:method name="update*" propagation="REQUIRED" />            <tx:method name="find*" propagation="SUPPORTS" read-only="true" />            <tx:method name="select*" propagation="SUPPORTS" read-only="true" />            <tx:method name="get*" propagation="SUPPORTS" read-only="true" />        </tx:attributes>    </tx:advice>    <!-- 切面 -->    <aop:config>        <aop:pointcut id="perform"                      expression="execution(* com.manage.service.Impl.*.*(..))"/>        <aop:advisor advice-ref="tx" pointcut-ref="perform"/>    </aop:config></beans>

   代码分析:

         首先在AOP之上建立的声明式事务管理,其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。其spring声明式底层都是使用了TransactionInterceptor。TransactionInterceptor是一个实现了MethodInterceptor接口的拦截器(Advice),具有相应的事务横切逻辑,被织入到系统中。若方法声明了相应的事务控制信息,它会在该方法执行前开启一个事务,完成时提交事务,发生异常时回滚事务,至于其中的具体规则(传播,隔离级别,超时时间,是否只读,针对何种异常进行回滚),在xml中事务策略中有详细配置。

   详细解析:

<tx:advice>是用来声明事务性策略的。对于<tx:advice>来说,事务属性定义在<tx:attributes>元素中,该元素包含了一个或多个的<tx:method>元素。<tx:method>元素为某个(或某些)name属性(使用通配符)指定的方法定义事务的参数。当然,当使用<tx:advice>来声明事务时,你还需要一个事务管理器,如代码中的transaction-manager="transactionManager"。

<tx:advice>只是定义了AOP通知,用于把事务边界通知给方法。但是这只是事务通知,而不是完整的事务性切面。我们在<tx:advice>中没有声明哪些Bean应该被通知——我们需要一个切点来做这件事。为了完整定义事务性切面,我们必须定义一个通知器(advisor)。这就涉及aop命名空间了。通过上面的配置示例可以看到:

这里的pointcut属性使用了AspectJ切入点表达式来表明通知器适用于com.manage.service.Impl包下的所有类的所有方法。哪些方法应该真正运行在事务中以及方法的事务属性都是由这个事务通知来定义的。而事务通知是advice-ref属性来指定的,它引用了名为tx的通知。


原创粉丝点击