Spring——Spring的事务控制(2)升级篇

1.改造转账案例

1.1.applicationContext.xml

 	
    <bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    bean>
    
    <bean class="org.springframework.transaction.support.DefaultTransactionDefinition">
        <property name="propagationBehaviorName" value="PROPAGATION_REQUIRED"/>
        <property name="readOnly" value="false">property>
    bean>

1.2.service

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private TransactionDefinition txDefinition;
    @Autowired
    private PlatformTransactionManager txManager;
    /**
     * 转账
     * @param source
     * @param target
     * @param money
     */
    @Override
    public void updateUser(String source, String target, Float money) {
        // 获取一个事务
        TransactionStatus txStatus = txManager.getTransaction(txDefinition);
        try {

            userMapper.updateUserOfSub(source, money);
            int a = 6/0;
            userMapper.updateUserOfAdd(target, money);
            //提交事务
            txManager.commit(txStatus);
        }catch (Exception e){
            //回滚事务
            txManager.rollback(txStatus);
            e.printStackTrace();
        }
    }
}

1.3.测试

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")//加载配置文件
public class ServiceTest {
    @Autowired
    private UserService userService;
    /**
     * 转账业务
     */
    @Test
    public void testUpdate(){
        userService.updateUser("张三丰","宋远桥",1F);
    }
}
  • 事务回滚:

    Spring——Spring的事务控制(2)升级篇_第1张图片

  • 满足执行:

    Spring——Spring的事务控制(2)升级篇_第2张图片

  • 我们现在虽然实现了事务控制,但是代码非常的臃肿,我们可以使用动态代理简化代码

2.动态代理控制事务

2.1.factory

我们创建一个工厂,专门用来给 Service 创建代理对象,如下:

package com.wt.factory;

import com.wt.service.UserService;
import com.wt.service.UserServiceImpl;
import org.hamcrest.Factory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * bean工厂
 */
@Component
public class BeanFactory {
    @Autowired
    private UserService userService;
    @Autowired
    private TransactionDefinition txDefinition;
    @Autowired
    private PlatformTransactionManager txManager;

    /**
     * 获得UserServiceImpl对象
     *
     * @return
     */
    public UserService getUserService() {
        return (UserService) Proxy.newProxyInstance(
            userService.getClass().getClassLoader(),
            userService.getClass().getInterfaces(),
            new InvocationHandler() {
                    public Object invoke(Object proxy, Method method, Object[] args)
                        											throws Throwable {
                        //开启事务
                        TransactionStatus txStatus = 
                            txManager.getTransaction(txDefinition);
                        try {
                            method.invoke(userService, args);
                            //提交事务
                            txManager.commit(txStatus);
                        } catch (Exception e) {
                            //回滚事务
                            txManager.rollback(txStatus);
                            e.printStackTrace();
                        }
                        return null;
                    }
                });
    }
}

2.2.applicationContext.xml


<bean id="proxyService" factory-bean="beanFactory" factory-method="getUserService">bean>

2.3.service

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;

    /**
     * 转账
     * @param source
     * @param target
     * @param money
     */
    @Override
    public void updateUser(String source, String target, Float money) {
        userMapper.updateUserOfSub(source, money);
        int a = 6/0;
        userMapper.updateUserOfAdd(target, money);
    }
}

2.4.测试

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class ServiceTest {
    @Autowired
    @Qualifier("proxyService")//注入代理对象
    private UserService userService;

    @Test
    public void testUpdate(){
        userService.updateUser("张三丰","宋远桥",1F);
    }
}
  • 事务回滚:

Spring——Spring的事务控制(2)升级篇_第3张图片

3.Spring AOP控制事务

3.1.导入schema约束


<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       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/context
       http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/tx
       http://www.springframework.org/schema/tx/spring-tx.xsd
       http://www.springframework.org/schema/aop
       https://www.springframework.org/schema/aop/spring-aop.xsd">
    
    
beans>    

3.2.配置增强

    
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        
        <tx:attributes>
        
        <tx:method name="*" read-only="false" propagation="REQUIRED"/>
        <tx:method name="select*" read-only="true" propagation="SUPPORTS"/>
        <tx:method name="get*" read-only="true" propagation="SUPPORTS"/>
       tx:attributes>
    tx:advice>

3.3.配置切点

    <aop:config>
        
        <aop:pointcut expression="execution(* com.wt.service.*.*(..))" id="pointcut"/>
    aop:config>

3.4.配置切面

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

3.5.factory

删除bean工程

3.6.测试

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")//加载配置文件
public class ServiceTest {
    @Autowired
    private UserService userService;
    /**
     * 转账业务
     */
    @Test
    public void testUpdate(){
        userService.updateUser("张三丰","宋远桥",1F);
    }
}
  • 事务回滚:

    Spring——Spring的事务控制(2)升级篇_第4张图片

  • 问题一:如果我们把方法名称改了,那么事务还会回滚吗?

    • 修改applicationContext.xml:

    Spring——Spring的事务控制(2)升级篇_第5张图片

    • 修改service:

    Spring——Spring的事务控制(2)升级篇_第6张图片

  • 问题二:如果我们把异常捕捉了,那么事务还会回滚吗?

    Spring——Spring的事务控制(2)升级篇_第7张图片

你可能感兴趣的:(Spring,spring)