黑马程序员技术交流社区

标题: [成都校区] [打印本页]

作者: object______du_    时间: 2019-4-13 15:07
标题: [成都校区]

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();
  }  } }




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2