Spring第三天
第1章 AOP的相关概念[理解]
1.1 AOP 概述
1.1.1 什么是 AOP
AOP:全称是 Aspect Oriented Programming 即:面向切面编程。
简单的说它就是把我们程序重复的代码抽取出来,在需要执行的时候,使用动态代理的技术,在不修改源码的
基础上,对我们的已有方法进行增强。
1.1.2 AOP 的作用及优势
作用: 在程序运行期间,不修改源码对已有方法进行增强。 优势: 减少重复代码 提高开发效率 维护方便
1.1.3 AOP 的实现方式
使用动态代理技术
1.2 AOP 的具体应用
1.2.1 案例中问题
这是我们昨天课程中做的增删改查例子。下面是客户的业务层实现类。我们能看出什么问题吗?
传智播客——专注于 Java、.Net 和Php、网页平面设计工程师的培训
北京市昌平区建材城西路金燕龙办公楼一层 电话:400-618-9090
客户的业务层实现类 /**
* 账户的业务层实现类 * @author 黑马程序员 * @Company http://www.ithiema.com * @Version 1.0 */ public class AccountServiceImpl implements IAccountService { private IAccountDao accountDao;
public void setAccountDao(IAccountDao accountDao) { this.accountDao = accountDao; }
@Override public void saveAccount(Account account) throws SQLException { accountDao.save(account); }
@Override public void updateAccount(Account account) throws SQLException{ accountDao.update(account); }
@Override public void deleteAccount(Integer accountId) throws SQLException{ accountDao.delete(accountId);
}
@Override public Account findAccountById(Integer accountId) throws SQLException { return accountDao.findById(accountId); }
@Override public List<Account> findAllAccount() throws SQLException{ return accountDao.findAll(); }
}
问题就是: 事务被自动控制了。换言之,我们使用了 connection 对象的 setAutoCommit(true) 此方式控制事务,如果我们每次都执行一条 sql 语句,没有问题,但是如果业务方法一次要执行多条 sql 语句,这种方式就无法实现功能了。
传智播客——专注于 Java、.Net 和Php、网页平面设计工程师的培训
北京市昌平区建材城西路金燕龙办公楼一层 电话:400-618-9090
请看下面的示例: 我们在业务层中多加入一个方法。
业务层接口 /**
* 转账 * @param sourceName * @param targetName * @param money */ void transfer(String sourceName,String targetName,Float money);
业务层实现类: @Override public void transfer(String sourceName, String targetName, Float money) { //根据名称查询两个账户信息 Account source = accountDao.findByName(sourceName); Account target = accountDao.findByName(targetName);
//转出账户减钱,转入账户加钱 source.setMoney(source.getMoney()-money); target.setMoney(target.getMoney()+money);
//更新两个账户 accountDao.update(source);
int i=1/0; //模拟转账异常 accountDao.update(target); }
当我们执行时,由于执行有异常,转账失败。但是因为我们是每次执行持久层方法都是独立事务,导致无法实
现事务控制(不符合事务的一致性)
1.2.2 问题的解决
解决办法: 让业务层来控制事务的提交和回滚。(这个我们之前已经在 web 阶段讲过了)
改造后的业务层实现类: 注:此处没有使用 spring的 IoC. /**
* 账户的业务层实现类 * @author 黑马程序员 * @Company http://www.ithiema.com * @Version 1.0 */ public class AccountServiceImpl implements IAccountService {
传智播客——专注于 Java、.Net 和Php、网页平面设计工程师的培训
北京市昌平区建材城西路金燕龙办公楼一层 电话:400-618-9090
private IAccountDao accountDao = new AccountDaoImpl();
@Override public void saveAccount(Account account) { try { TransactionManager.beginTransaction(); accountDao.save(account);
TransactionManager.commit(); } catch (Exception e) { TransactionManager.rollback(); e.printStackTrace(); }finally { TransactionManager.release();
} }
@Override public void updateAccount(Account account) { try { TransactionManager.beginTransaction(); accountDao.update(account); TransactionManager.commit(); } catch (Exception e) { TransactionManager.rollback(); e.printStackTrace(); }finally { TransactionManager.release();
} }
@Override public void deleteAccount(Integer accountId) { try { TransactionManager.beginTransaction(); accountDao.delete(accountId); TransactionManager.commit(); } catch (Exception e) { TransactionManager.rollback();
e.printStackTrace(); }finally { TransactionManager.release();
} }
传智播客——专注于 Java、.Net 和Php、网页平面设计工程师的培训
北京市昌平区建材城西路金燕龙办公楼一层 电话:400-618-9090
@Override public Account findAccountById(Integer accountId) { Account account = null; try { TransactionManager.beginTransaction(); account = accountDao.findById(accountId); TransactionManager.commit(); return account; } catch (Exception e) { TransactionManager.rollback(); e.printStackTrace(); }finally { TransactionManager.release();
} return null; }
@Override public List<Account> findAllAccount() { List<Account> accounts = null; try { TransactionManager.beginTransaction(); accounts = accountDao.findAll(); TransactionManager.commit(); return accounts; } catch (Exception e) { TransactionManager.rollback();
e.printStackTrace(); }finally { TransactionManager.release(); } return null; }
@Override public void transfer(String sourceName, String targetName, Float money) { try { TransactionManager.beginTransaction();
Account source = accountDao.findByName(sourceName); Account target = accountDao.findByName(targetName); source.setMoney(source.getMoney()-money);
target.setMoney(target.getMoney()+money); accountDao.update(source);
传智播客——专注于 Java、.Net 和Php、网页平面设计工程师的培训
北京市昌平区建材城西路金燕龙办公楼一层 电话:400-618-9090
int i=1/0; accountDao.update(target); TransactionManager.commit(); } catch (Exception e) { TransactionManager.rollback();
e.printStackTrace(); }finally { TransactionManager.release();
} }
}
TransactionManager 类的代码: /**
* 事务控制类 * @author 黑马程序员 * @Company http://www.ithiema.com * @Version 1.0 */ public class TransactionManager {
//定义一个 DBAssit private static DBAssit dbAssit = new DBAssit(C3P0Utils.getDataSource(),true);
//开启事务 public static void beginTransaction() { try { dbAssit.getCurrentConnection().setAutoCommit(false); } catch (SQLException e) { e.printStackTrace(); } }
//提交事务 public static void commit() { try { dbAssit.getCurrentConnection().commit(); } catch (SQLException e) { e.printStackTrace(); } }
//回滚事务
传智播客——专注于 Java、.Net 和Php、网页平面设计工程师的培训
北京市昌平区建材城西路金燕龙办公楼一层 电话:400-618-9090
public static void rollback() { try { dbAssit.getCurrentConnection().rollback(); } catch (SQLException e) { e.printStackTrace();
} }
//释放资源 public static void release() { try { dbAssit.releaseConnection(); } catch (Exception e) { e.printStackTrace();
} } } |
|