博客
关于我
基于注解的AOP实现事务控制
阅读量:687 次
发布时间:2019-03-17

本文共 11070 字,大约阅读时间需要 36 分钟。

需要注意在使用注解时,后置通知与异常通知执行顺序颠倒,所以要用环绕通知来解决此问题。

pom.xml

4.0.0
com.qublog
spring04_account_aoptx_anno
1.0-SNAPSHOT
jar
org.springframework
spring-context
5.0.2.RELEASE
commons-dbutils
commons-dbutils
1.4
mysql
mysql-connector-java
8.0.16
c3p0
c3p0
0.9.1.2
junit
junit
4.12
org.springframework
spring-test
5.0.2.RELEASE
org.aspectj
aspectjweaver
1.8.7

Account类:

package com.qublog.domain;import java.io.Serializable;//账户的实体类public class Account implements Serializable {       private Integer id;    private String name;    private Float money;    public Integer getId() {           return id;    }    public void setId(Integer id) {           this.id = id;    }    public String getName() {           return name;    }    public void setName(String name) {           this.name = name;    }    public Float getMoney() {           return money;    }    public void setMoney(Float money) {           this.money = money;    }    @Override    public String toString() {           return "Account{" +                "id=" + id +                ", name='" + name + '\'' +                ", money=" + money +                '}';    }}

AccountDao接口:

package com.qublog.dao;import com.qublog.domain.Account;import java.util.List;//账户的持久层接口public interface AccountDao {       //查询所有    List
findAllAccount(); //查询一个 Account findAccountById(Integer id); //保存 void saveAccount(Account account); //更新 void updateAccount(Account account); //删除 void deleteAccount(Integer id); //根据名称查找账户,如果有唯一结果就返回,如果没有结果就返回null,如果结果集超过一个就抛异常 Account findAccountByName(String accountName);}

AccountDaoImpl类:

package com.qublog.dao.impl;import com.qublog.dao.AccountDao;import com.qublog.domain.Account;import com.qublog.utils.ConnectionUtils;import org.apache.commons.dbutils.QueryRunner;import org.apache.commons.dbutils.handlers.BeanHandler;import org.apache.commons.dbutils.handlers.BeanListHandler;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Repository;import java.util.List;//账户的持久层实现类@Repository("accountDao")public class AccountDaoImpl implements AccountDao {       @Autowired    private QueryRunner runner;    @Autowired    private ConnectionUtils connectionUtils;    public List
findAllAccount() { try{ return runner.query(connectionUtils.getThreadConnection(),"select * from account;",new BeanListHandler
(Account.class)); } catch (Exception e) { throw new RuntimeException(e); } } public Account findAccountById(Integer id) { try{ return runner.query(connectionUtils.getThreadConnection(),"select * from account where id=?;",new BeanHandler
(Account.class),id); } catch (Exception e) { throw new RuntimeException(e); } } public void saveAccount(Account account) { try{ runner.update(connectionUtils.getThreadConnection(),"insert into account(name,money) values(?,?);", account.getName(), account.getMoney()); } catch (Exception e) { throw new RuntimeException(e); } } public void updateAccount(Account account) { try{ runner.update(connectionUtils.getThreadConnection(),"update account set name=?,money=? where id=?;", account.getName(), account.getMoney(),account.getId()); } catch (Exception e) { throw new RuntimeException(e); } } public void deleteAccount(Integer id) { try{ runner.update(connectionUtils.getThreadConnection(),"delete from account where id=?;",id); } catch (Exception e) { throw new RuntimeException(e); } } public Account findAccountByName(String accountName) { try { List
accounts = runner.query(connectionUtils.getThreadConnection(),"select * from account where name = ?",new BeanListHandler
(Account.class),accountName); if (accounts == null || accounts.size() == 0) { return null; } if (accounts.size() > 1) { throw new RuntimeException("结果集不唯一,数据有问题"); } return accounts.get(0); } catch (Exception e) { throw new RuntimeException(e); } }}

AccountService接口:

package com.qublog.service;import com.qublog.domain.Account;import java.util.List;//账户的业务层接口public interface AccountService {       //查询所有    List
findAllAccount(); //查询一个 Account findAccountById(Integer id); //保存 void saveAccount(Account account); //更新 void updateAccount(Account account); //删除 void deleteAccount(Integer id); //转账 void transfer(String sourceName, String targetName, Float money); //void test();}

AccountServiceImpl类:

package com.qublog.service.impl;import com.qublog.dao.AccountDao;import com.qublog.domain.Account;import com.qublog.service.AccountService;import com.qublog.utils.TransactionManager;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import java.util.List;//账户的业务层实现类//事务的控制应该都是在业务层的@Service("accountService")public class AccountServiceImpl implements AccountService {       @Autowired    private AccountDao accountDao;    public List
findAllAccount() { return accountDao.findAllAccount(); } public Account findAccountById(Integer id) { return accountDao.findAccountById(id); } public void saveAccount(Account account) { accountDao.saveAccount(account); } public void updateAccount(Account account) { accountDao.updateAccount(account); } public void deleteAccount(Integer id) { accountDao.deleteAccount(id); } public void transfer(String sourceName, String targetName, Float money) { System.out.println("transfer..."); //根据名称查询转出账户 Account source = accountDao.findAccountByName(sourceName); //根据名称查询转入账户 Account target = accountDao.findAccountByName(targetName); //转出账户减钱 source.setMoney(source.getMoney()-money); //转入账户加钱 target.setMoney(target.getMoney()+money); //更新转出账户 accountDao.updateAccount(source); int i=1/0; //更新转入账户 accountDao.updateAccount(target); }}

ConnectionUtils类:

package com.qublog.utils;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import javax.sql.DataSource;import java.sql.Connection;//连接的工具类,它用于从数据源中获取一个连接,并且实现和线程的绑定@Component("connectionUtils")public class ConnectionUtils {       private ThreadLocal
tl = new ThreadLocal
(); @Autowired private DataSource dataSource; //获取当前线程上的连接 public Connection getThreadConnection() { try { //先从ThreadLocal上获取 Connection conn = tl.get(); //判断当前线程上是否有连接 if (conn == null) { //从数据源中获取一个连接,并且存入ThreadLocal中 conn = dataSource.getConnection(); tl.set(conn); } //返回当前线程上的连接 return conn; } catch (Exception e) { throw new RuntimeException(e); } } //把连接和线程解绑 public void removeConnection() { tl.remove(); }}

TransactionManager类:

package com.qublog.utils;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.*;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;//和事务管理相关的工具类,包含了,开启事务,提交事务,回滚事务,释放连接@Component("txManager")@Aspectpublic class TransactionManager {       @Autowired    private ConnectionUtils connectionUtils;    @Pointcut("execution(* com.qublog.service.impl.*.*(..))")    private void pt1() {   }    //开启事务    public void beginTransaction() {           try {               connectionUtils.getThreadConnection().setAutoCommit(false);        } catch (Exception e) {               e.printStackTrace();        }    }    //提交事务    public void commit() {           try {               connectionUtils.getThreadConnection().commit();        } catch (Exception e) {               e.printStackTrace();        }    }    //回滚事务    public void rollback() {           try {               connectionUtils.getThreadConnection().rollback();        } catch (Exception e) {               e.printStackTrace();        }    }    //释放连接    public void release() {           try {               connectionUtils.getThreadConnection().close();//还回连接池中            connectionUtils.removeConnection();        } catch (Exception e) {               e.printStackTrace();        }    }    @Around("pt1()")    public Object aroundAdvice(ProceedingJoinPoint pjp) {           Object rtValue = null;        try {               //获取参数            Object[] args = pjp.getArgs();            //开启事务            this.beginTransaction();            //执行方法            rtValue = pjp.proceed(args);            //提交事务            this.commit();            //返回结果            return rtValue;        } catch (Throwable t) {               //回滚事务            this.rollback();            throw new RuntimeException(t);        } finally {               //释放资源            this.release();        }    }}

bean.xml

AccountServiceTest类:

package com.qublog.test;import com.qublog.service.AccountService;import org.junit.Test;import org.junit.runner.RunWith;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.test.context.ContextConfiguration;import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;//使用Junit单元测试,测试我们的配置@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration(locations = "classpath:bean.xml")public class AccountServiceTest {       @Autowired    private AccountService as;    @Test    public void testTransfer() {           as.transfer("aaa","bbb",100f);    }}

转载地址:http://dfchz.baihongyu.com/

你可能感兴趣的文章
MQTT工作笔记0007---剩余长度
查看>>
MQTT工作笔记0009---订阅主题和订阅确认
查看>>
Mqtt搭建代理服务器进行通信-浅析
查看>>
MS Edge浏览器“STATUS_INVALID_IMAGE_HASH“兼容性问题
查看>>
ms sql server 2008 sp2更新异常
查看>>
MS UC 2013-0-Prepare Tool
查看>>
MSBuild 教程(2)
查看>>
msbuild发布web应用程序
查看>>
MSB与LSB
查看>>
MSCRM调用外部JS文件
查看>>
MSCRM调用外部JS文件
查看>>
MSEdgeDriver (Chromium) 不适用于版本 >= 79.0.313 (Canary)
查看>>
MsEdgeTTS开源项目使用教程
查看>>
msf
查看>>
MSSQL数据库查询优化(一)
查看>>
MSSQL数据库迁移到Oracle(二)
查看>>
MSSQL日期格式转换函数(使用CONVERT)
查看>>
MSTP多生成树协议(第二课)
查看>>
MSTP是什么?有哪些专有名词?
查看>>
Mstsc 远程桌面链接 And 网络映射
查看>>