SpringAOP应用之事务处理

SpringAOP应用之事务处理

一.引言

在Java服务端应用开发过程,Spring框架具有着举足轻重的作用,spring的出现为我们原本一些复杂的操作进行了透明化的封装,使得开发人员在编写代码时更加简洁,只需要把关注自己的业务即可;
Spring框架的的两大作用:
1.IOC(控制反转),DI(依赖注入)
2.AOP (对特定的方法进行功能增强)
本章我们主要讨论Spring的AOP技术,在Spring框架中AOP技术应用最为经典的案例就是对于事务的相关处理,下面就从Spring事务管理出发,帮助大家更好的理解SpringAOP技术的应用;

二.SpringAOP 在事务管理中的应用

1.技术背景

在介绍Spring事务管理之前,我们有必要先了解一下Spring框架中常用的AOP技术:
(1)JDK 动态代理
(2)CGLIB 动态代理
(3)Aspectj 编译时动态植入增强代码
三种方式增强方法的区别:JDK动态代理,CGLB动态代理是在运行重新生成一个class文件,在新生成class文件中对原理的对原有的代码逻辑进行了增强;Aspectj与前两者有所不同,Aspectj是在编译阶段将我们要增强的代码植入到原有class文件中;
这里我们对三种AOP增强技术不做过多的介绍,如果想了解三种AOP技术请关注我得其他文章;

2.SpringAOP思想在Spring事务管理中的应用

在Spring框架中对于事务的处理从大的分类上可以分为两大类:
a.编程式事务
b.声明式事务
但是无论是那种事务管理方式都是基于PlatformTransactionManager进行管理的,只是实现的形式有所不同而已;

1.编程式事务

案例1.

<?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:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/context
                           http://www.springframework.org/schema/context/spring-context.xsd">

    <context:property-placeholder location="classpath:jdbc.properties"/>
     <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">

         <property name="username" value="${jdbc.username}"/>
         <property name="password" value="${jdbc.password}"/>
         <property name="url" value="${jdbc.url}"/>
         <property name="driverClassName" value="${jdbc.driverClass}"/>
     </bean>

    <!-- 配置平台事务管理器 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <!-- 配置事务管理的模板 -->
    <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
        <property name="transactionManager" ref="transactionManager"/>
    </bean>

</beans>
public class TestTranscation {

    public static void main(String[] args) {
       final ClassPathXmlApplicationContext cl = new ClassPathXmlApplicationContext("Transcation.xml");
        final TransactionTemplate transactionTemplate = (TransactionTemplate) cl.getBean("transactionTemplate");
        /*基于TransactionTemplate模板方式实现编程式事务控制*/
       transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {

      /**
      相关业务代码
      */
            }
        });
     }
}

这种方式实现的事务实际上使用的模板方法的设计模式,如果想了解原理可以跟踪 transactionTemplate.execute()源码,我们返现在该方法中已经定义好了事务的开启,提交,回滚等逻辑,同时回调了一下我们自定的业务代码块doInTransactionWithoutResult(TransactionStatus transactionStatus);如果想了解实现原理可以自行跟踪代码,这里不做过多解释;

2.声明式事务

了解过编程事务后我们发现,虽然编程式事务已经对事务处理进行了很好的封装,但是对于开发人员来说还是需要关心事务先关代码的编写,至少需要知道这种模板方式的实现原理;下面为大家介绍一种更为简便的Spring管理事务的方法;
(1)@Transaction注解方式的声明式事务
案例1.

<?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:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/aop
       https://www.springframework.org/schema/aop/spring-aop.xsd
       http://www.springframework.org/schema/tx
       https://www.springframework.org/schema/tx/spring-tx.xsd
">
    <context:component-scan base-package="com.transaction"></context:component-scan>
    <context:property-placeholder location="classpath:dbconfig.properties"></context:property-placeholder>
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="username" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
        <property name="url" value="${jdbc.url}"></property>
        <property name="driverClassName" value="${jdbc.driverClassName}"></property>
    </bean>
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <constructor-arg name="dataSource" ref="dataSource"></constructor-arg>
    </bean>
    <!--事务控制-->
    <!--配置事务管理器的bean-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <!--开启基于注解的事务控制模式,依赖tx名称空间-->
    <tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
</beans>
@Service
public class BookService {

    @Autowired
    BookDao bookDao;

    /**
     * @param username
     * @param id
     */
    @Transactional //使用事务注解实现事务管理
    public void checkout(String username,int id){

        bookDao.updateStock(id);
        int price = bookDao.getPrice(id);
        bookDao.updateBalance(username,price);
    }
}

(2)基于切面通知的声明式事务
案例1.

<?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:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/aop
       https://www.springframework.org/schema/aop/spring-aop.xsd
       http://www.springframework.org/schema/tx
       https://www.springframework.org/schema/tx/spring-tx.xsd
">
    <context:component-scan base-package="com.transaction"></context:component-scan>
    <context:property-placeholder location="classpath:dbconfig.properties"></context:property-placeholder>
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="username" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
        <property name="url" value="${jdbc.url}"></property>
        <property name="driverClassName" value="${jdbc.driverClassName}"></property>
    </bean>
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <constructor-arg name="dataSource" ref="dataSource"></constructor-arg>
    </bean>
    <bean id="namedParameterJdbcTemplate" class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">
        <constructor-arg name="dataSource" ref="dataSource"></constructor-arg>
    </bean>
    <!--事务控制-->
    <!--配置事务管理器的bean-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <!--
    基于xml配置的事务:依赖tx名称空间和aop名称空间
        1、spring中提供事务管理器(切面),配置这个事务管理器
        2、配置出事务方法
        3、告诉spring哪些方法是事务方法(事务切面按照我们的切入点表达式去切入事务方法)
    -->
    <bean id="bookService" class="com.transaction.service.BookService"></bean>
    <aop:config>
        <aop:pointcut id="txPoint" expression="execution(* com.transaction.service.*.*(..))"/>
        <!--事务建议:advice-ref:指向事务管理器的配置-->
        <aop:advisor advice-ref="myAdvice" pointcut-ref="txPoint"></aop:advisor>
    </aop:config>
    <tx:advice id="myAdvice" transaction-manager="transactionManager">
        <!--事务属性-->
        <tx:attributes>
            <!--指明哪些方法是事务方法-->
            <tx:method name="*"/>
            <tx:method name="checkout" propagation="REQUIRED"/>
            <tx:method name="get*" read-only="true"></tx:method>
        </tx:attributes>
    </tx:advice>
</beans>

使用这种方式可以将事务的作用于精确作用到一个点或者一面上;

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值