博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
基于注解的AOP实现事务控制
阅读量:685 次
发布时间:2019-03-17

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

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

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/

你可能感兴趣的文章