spring手动控制事务开启_Spring:AOP 面向切面编程

本文通过一个转账案例介绍了如何在 Spring 中手动控制事务,并详细讲解了 AOP(面向切面编程)的概念、底层实现、相关术语和两种动态代理方式(JDK 和 CGLIB)。此外,还提供了基于 XML 和注解的 AOP 开发教程,以及如何利用 AOP 优化转账案例。
摘要由CSDN通过智能技术生成
d841e815c5b6d3bf0fa3026bb4c18bd8.png

转账案例

需求:使用 spring 框架整合 DBUtils 技术,实现用户转账功能

基础功能

步骤分析:

  1. 创建 java 项目,导入坐标
  2. 编写 Account 实体类
  3. 编写 AccountDao 接口和实现类
  4. 编写 AccountService 接口和实现类
  5. 编写 spring 核心配置文件
  6. 编写测试代码

创建 java 项目,导入坐标

mysql        mysql-connector-java        5.1.47com.alibaba        druid        1.1.15​    commons-dbutils        commons-dbutils        1.6​    org.springframework        spring-context        5.1.5.RELEASE​    org.springframework        spring-test        5.1.5.RELEASE​    junit        junit        4.12​    org.aspectj        aspectjweaver        1.8.13

编写 AccountDao 接口和实现类

public interface AccountDao {    /**     * 转出操作     * @param outUser     * @param money     */    void out(String outUser,Double money);​    /**     * 转入操作     * @param inUser     * @param money     */    void in(String inUser,Double money);}@Repository("AccountDao")public class AccountDaoImpl implements AccountDao {    @Autowired    private QueryRunner queryRunner;​    @Override    public void out(String outUser, Double money) {        String sql = "update account set money = money - ? where name = ?";        try {            queryRunner.update(sql, money, outUser);        } catch (SQLException throwables) {            throwables.printStackTrace();        }    }​    @Override    public void in(String inUser, Double money) {        String sql = "update account set money = money + ? where name = ?";        try {            queryRunner.update(sql, money, inUser);        } catch (SQLException throwables) {            throwables.printStackTrace();        }    }}

编写 AccountService 接口和实现类

public interface AccountService {        /**         * 转账方法         */        void transfer(String outUser,String inUser,Double money);}@Service("accountService")public class AccountServiceImpl implements AccountService {    @Autowired    private AccountDao accountDao;    /**     * 转账方法     */    @Override    public void transfer(String outUser, String inUser, Double money) {        // 编写了事务相关代码        // 调用了减钱方法        accountDao.out(outUser,money);        // 模拟出错        // int i= 1/0;        // 调用了加钱方法        accountDao.in(inUser,money);    }}

编写 spring 核心配置文件

<?xml version="1.0" encoding="UTF-8"?>

编写测试代码

@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration({"classpath:applicationContext.xml"})public class AccountServiceTest {    @Autowired    private AccountService accountService;    @Test    public void testTransfer() {        accountService.transfer("tom", "jerry", 100d);    }}

问题分析

上面的代码事务在 Dao 层,转出转入操作都是一个独立的事务,但实际开发,应该把业务逻辑控制在一个事务中,所以应该将事务挪到 Service 层。

传统事务

步骤分析:

  1. 编写线程绑定工具类
  2. 编写事务管理器
  3. 修改 service 层代码
  4. 修改 dao 层代码

编写线程绑定工具类

@Componentpublic class ConnectionUtils {    @Autowired    private DataSource dataSource;​    private ThreadLocal threadLocal = new ThreadLocal<>();​    /**     * 获取当前线程上绑定连接:如果获取到的连接为空,那么就要从数据源中获取连接,并且放到 ThreadLocal 中(绑定到当前线程)     */    public Connection getThreadConnection() {        // 1.先从 ThreadLocal 上获取连接        Connection connection = threadLocal.get();        // 2.判断当前线程中是否是有 Connection        if(connection == null){            // 3.从数据源中获取一个连接,并且存入 ThreadLocal 中            try {                // 不为 null                connection = dataSource.getConnection();                threadLocal.set(connection);            } catch (SQLException e) {                e.printStackTrace();            }        }        return  connection;    }​    /**     * 解除当前线程的连接绑定     */    public void  removeThreadConnection(){        threadLocal.remove();    }}

编写事务管理器

@Component("transactionManager")public class TransactionManager {    @Autowired    private ConnectionUtils connectionUtils;​    /**     * 开启事务     */    public void beginTransaction(){        // 获取 connection 对象        Connection connection = connectionUtils.getThreadConnection();        try {            // 开启了一个手动事务            connection.setAutoCommit(false);        } catch (SQLException e) {            e.printStackTrace();        }    }​    /**     * 提交事务     */    public void commit(){        Connection connection = connectionUtils.getThreadConnection();        try {            connection.commit();        } catch (SQLException e) {            e.printStackTrace();        }    }​    /**     * 回滚事务     */    public void rollback(){        Connection connection = connectionUtils.getThreadConnection();        try {            connection.rollback();        } catch (SQLException e) {            e.printStackTrace();        }    }​    /**     * 释放资源     */    public void release(){        // 将手动事务改回成自动提交事务        Connection connection = connectionUtils.getThreadConnection();        try {            connection.setAutoCommit(true);            // 将连接归还到连接池            connectionUtils.getThreadConnection().close();            // 解除线程绑定            connectionUtils.removeThreadConnection();      
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值