zoukankan      html  css  js  c++  java
  • spring 技术详解 教程(三)

    案例一:使用 Spring 的 AOP 对客户管理的
    DAO 进行增强
    1.1案例需求
    1.1.1 需求描述
    对于 CRM 的系统而言,现在有很多的 DAO 类,比如客户的 DAO,联系人 DAO 等等。客户提
    出一个需求要开发人员实现一个功能对所有的 DAO 的类中以 save 开头的方法实现权限的校验,需
    要时管理员的身份才可以进行保存操作。
    1.2相关知识点
    1.2.1 Spring 使用 AspectJ 进行 AOP 的开发:注解的方式
    1.2.1.1 引入相关的 jar 包:

    • spring 的传统 AOP 的开发的包
      spring-aop-4.2.4.RELEASE.jar
      com.springsource.org.aopalliance-1.0.0.jar
    • aspectJ 的开发包:
      com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
      spring-aspects-4.2.4.RELEASE.jar
      1.2.1.2 引入 Spring 的配置文件
      引入 AOP 约束:


      1.2.1.3 编写目标类:
      public class ProductDao {
      public void save(){
      System.out.println("保存商品...");
      }
      public void update(){
      System.out.println("修改商品...");
      }
      public void delete(){
      System.out.println("删除商品...");
      }
      public void find(){
      System.out.println("查询商品...");
      }
      }
      1.2.1.4 配置目标类:


    1.2.1.5 开启 aop 注解的自动代理:
    aop:aspectj-autoproxy/
    1.2.1.6 AspectJ 的 AOP 的注解:
    @Aspect:定义切面类的注解
    通知类型:

    • @Before
      :前置通知
    • @AfterReturing
      :后置通知
    • @Around
      :环绕通知
    • @After
      :最终通知
    • @AfterThrowing
      :异常抛出通知.
      @Pointcut:定义切入点的注解
      1.2.1.7 编写切面类:
      @Aspect
      public class MyAspectAnno {
      @Before("MyAspectAnno.pointcut1()")
      public void before(){
      System.out.println("前置通知===========");
      }
      @Pointcut("execution(* cn.itcast.spring.demo4.ProductDao.save(..))")
      private void pointcut1(){}
      }
      1.2.1.8 配置切面:


    1.2.1.9 其他通知的注解:
    @Aspect
    public class MyAspectAnno {
    @Before("MyAspectAnno.pointcut1()")
    public void before(){
    System.out.println("前置通知=");
    }
    @AfterReturning("MyAspectAnno.pointcut2()")
    public void afterReturning(){
    System.out.println("后置通知
    =");
    }
    @Around("MyAspectAnno.pointcut3()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable{
    System.out.println("环绕前通知");
    Object obj = joinPoint.proceed();
    System.out.println("环绕后通知
    ");
    return obj;
    }
    @AfterThrowing("MyAspectAnno.pointcut4()")
    public void afterThrowing(){
    System.out.println("异常抛出通知");
    }
    @After("MyAspectAnno.pointcut4()")
    public void after(){
    System.out.println("最终通知
    ==");
    }
    @Pointcut("execution(* cn.itcast.spring.demo4.ProductDao.save(..))")
    private void pointcut1(){}
    @Pointcut("execution(* cn.itcast.spring.demo4.ProductDao.update(..))")
    private void pointcut2(){}
    @Pointcut("execution(* cn.itcast.spring.demo4.ProductDao.delete(..))")
    private void pointcut3(){}
    @Pointcut("execution(* cn.itcast.spring.demo4.ProductDao.find(..))")
    private void pointcut4(){}
    }
    案例二:Spring的事务管理完成转账的案例
    1.3案例需求:
    1.3.1 需求描述:
    完成一个转账的功能,需要进行事务的管理,使用 Spring 的事务管理的方式完成.
    1.4相关知识点
    1.4.1 Spring 的 JDBC 的模板:
    1.4.1.1 Spring 提供了很多持久层技术的模板类简化编程:
    1.4.1.2 创建数据库和表:
    1.4.1.3 引入相关开发包:
    Spring 的基本的开发包需要引入的:6 个.
    1.4.1.4 创建一个测试类:
    @Test
    // JDBC 模板的基本使用:
    public void demo1(){
    DriverManagerDataSource dataSource = new DriverManagerDataSource();
    dataSource.setDriverClassName("com.mysql.jdbc.Driver");
    dataSource.setUrl("jdbc:mysql:///spring_day03");
    dataSource.setUsername("root");
    dataSource.setPassword("123");
    JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
    jdbcTemplate.update("insert into account values (null,?,?)", " 会 希
    ",10000d);
    }
    1.4.2 将连接池的配置交给 Spring 管理:
    1.4.2.1 Spring 内置的连接池的配置:
    【引入 Spring 的配置文件】
    【配置内置连接池】







    【将模板配置到 Spring 中】

    【编写测试类】 **** 引入 spring-aop.jar @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:applicationContext.xml") public class SpringDemo2 { @Resource(name="jdbcTemplate") private JdbcTemplate jdbcTemplate; @Test public void demo1(){ jdbcTemplate.update("insert into account values (null,?,?)", " 凤 姐 ",10000d); } } 1.4.2.2 Spring 中配置 DBCP 连接池: 【引入 dbcp 连接池的 jar 包】 【配置连接池】 1.4.2.3 配置 c3p0 连接池: 【引入相应的 jar 包】 com.springsource.com.mchange.v2.c3p0-0.9.1.2.jar 【配置连接池】 1.4.2.4 将数据库连接的信息配置到属性文件中: 【定义属性文件】 jdbc.driverClass=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql:///spring_day02 jdbc.username=root jdbc.password=123 【引入外部的属性文件】 一种方式: 二种方式: 1.4.3 JDBC 模板的 CRUD 的操作: 1.4.3.1 JDBC 模板 CRUD 的操作: @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:applicationContext.xml") public class SpringDemo3 { @Resource(name="jdbcTemplate") private JdbcTemplate jdbcTemplate; @Test // 插入操作 public void demo1(){ jdbcTemplate.update("insert into account values (null,?,?)", " 冠 希 ",10000d); } @Test // 修改操作 public void demo2(){ jdbcTemplate.update("update account set name=?,money =? where id = ?", " 思雨",10000d,5); } @Test // 删除操作 public void demo3(){ jdbcTemplate.update("delete from account where id = ?", 5); } @Test // 查询一条记录 public void demo4(){ Account account = jdbcTemplate.queryForObject("select * from account where id = ?", new MyRowMapper(), 1); System.out.println(account); } @Test // 查询所有记录 public void demo5(){ List list = jdbcTemplate.query("select * from account", new MyRowMapper()); for (Account account : list) { System.out.println(account); } } class MyRowMapper implements RowMapper{ @Override public Account mapRow(ResultSet rs, int rowNum) throws SQLException { Account account = new Account(); account.setId(rs.getInt("id")); account.setName(rs.getString("name")); account.setMoney(rs.getDouble("money")); return account; } } } 1.4.4 事务的回顾: 1.4.4.1 什么是事务: 事务逻辑上的一组操作,组成这组操作的各个逻辑单元,要么一起成功,要么一起失败. 1.4.4.2 事务特性: 原子性 :强调事务的不可分割. 一致性 :事务的执行的前后数据的完整性保持一致. 隔离性 :一个事务执行的过程中,不应该受到其他事务的干扰 持久性 :事务一旦结束,数据就持久到数据库 1.4.4.3 如果不考虑隔离性引发安全性问题: 脏读 :一个事务读到了另一个事务的未提交的数据 不可重复读 :一个事务读到了另一个事务已经提交的 update 的数据导致多次查询结果不一致. 虚幻读 :一个事务读到了另一个事务已经提交的 insert 的数据导致多次查询结果不一致. 1.4.4.4 解决读问题:设置事务隔离级别 未提交读 :脏读,不可重复读,虚读都有可能发生 已提交读 :避免脏读。但是不可重复读和虚读有可能发生 可重复读 :避免脏读和不可重复读.但是虚读有可能发生. 串行化的 :避免以上所有读问题. Mysql 默认:可重复读 Oracle 默认:读已提交 1.4.5 Spring 进行事务管理一组 API 1.4.5.1 PlatformTransactionManager:平台事务管理器. ***** 真正管理事务的对象 org.springframework.jdbc.datasource.DataSourceTransactionManager 使用 Spring JDBC 或 iBatis 进行持久化数据时使用 org.springframework.orm.hibernate3.HibernateTransactionManager 使用 Hibernate 版本进行持久化数据时使用 1.4.5.2 TransactionDefinition:事务定义信息 事务定义信息: * 隔离级别 * 传播行为 * 超时信息 * 是否只读 1.4.5.3 TransactionStatus:事务的状态 记录事务的状态 1.4.5.4 Spring 的这组接口是如何进行事务管理: 平台事务管理根据事务定义的信息进行事务的管理,事务管理的过程中产生一些状态,将这些状态记 录到 TransactionStatus 里面 1.4.5.5 事务的传播行为 PROPAGION_XXX :事务的传播行为 * 保证同一个事务中 PROPAGATION_REQUIRED 支持当前事务,如果不存在 就新建一个(默认) PROPAGATION_SUPPORTS 支持当前事务,如果不存在,就不使用事务 PROPAGATION_MANDATORY 支持当前事务,如果不存在,抛出异常 * 保证没有在同一个事务中 PROPAGATION_REQUIRES_NEW 如果有事务存在,挂起当前事务,创建一个新的事务 PROPAGATION_NOT_SUPPORTED 以非事务方式运行,如果有事务存在,挂起当前事务 PROPAGATION_NEVER 以非事务方式运行,如果有事务存在,抛出异常 PROPAGATION_NESTED 如果当前事务存在,则嵌套事务执行 1.5案例代码 1.5.1 搭建转账的环境: 1.5.1.1 创建业务层和 DAO 的类 public interface AccountService { public void transfer(String from,String to,Double money); } public class AccountServiceImpl implements AccountService { // 业务层注入 DAO: private AccountDao accountDao; public void setAccountDao(AccountDao accountDao) { this.accountDao = accountDao; } @Override /** * from:转出的账号 * to:转入的账号 * money:转账金额 */ public void transfer(String from, String to, Double money) { accountDao.outMoney(from, money); accountDao.inMoney(to, money); } } public interface AccountDao { public void outMoney(String from,Double money); public void inMoney(String to,Double money); } public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao { @Override public void outMoney(String from, Double money) { this.getJdbcTemplate().update("update account set money = money - ? where name = ?", money,from); } @Override public void inMoney(String to, Double money) { this.getJdbcTemplate().update("update account set money = money + ? where name = ?", money,to); } } 1.5.1.2 配置业务层和 DAO 1.5.1.3 编写测试类 @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:applicationContext2.xml") public class SpringDemo4 { @Resource(name="accountService") private AccountService accountService; @Test // 转账的测试: public void demo1(){ accountService.transfer("会希", "凤姐", 1000d); } } 1.5.2 Spring 的编程式事务(了解) 手动编写代码完成事务的管理: 1.5.2.1 配置事务管理器 1.5.2.2 配置事务管理的模板 1.5.2.3 需要在业务层注入事务管理模板 1.5.2.4 手动编写代码实现事务管理 public void transfer(final String from, final String to, final Double money) { transactionTemplate.execute(new TransactionCallbackWithoutResult() { @Override protected void doInTransactionWithoutResult(TransactionStatus status) { accountDao.outMoney(from, money); int d = 1 / 0; accountDao.inMoney(to, money); } }); } 1.5.3 Spring 的声明式事务管理 XML 方式(*****):思想就是 AOP. 不需要进行手动编写代码,通过一段配置完成事务管理 1.5.3.1 引入 AOP 开发的包 aop 联盟.jar Spring-aop.jar aspectJ.jar spring-aspects.jar 1.5.3.2 恢复转账环境 1.5.3.3 配置事务管理器 1.5.3.4 配置事务的通知 1.5.3.5 配置 aop 事务 1.5.4 Spring 的声明式事务的注解方式: (*****) 1.5.4.1 引入 jar 包: 1.5.4.2 恢复转账环境: 1.5.4.3 配置事务管理器: 1.5.4.4 开启事务管理的注解: 1.5.4.5 在使用事务的类上添加一个注解:@Transactional
  • 相关阅读:
    9.11 eventbus
    9.10,,,实现new instanceof apply call 高阶函数,偏函数,柯里化
    9.9 promise实现 写完了传到gitee上面了,这里这个不完整
    9.5cors配置代码
    9.5 jsonp 实现
    9.5 http tcp https总结
    9.3 es6 class一部分 and es5 class 发布订阅
    8.30 cookie session token jwt
    8.30vue响应式原理
    warning: LF will be replaced by CRLF in renard-wx/project.config.json. The file will have its original line endings in your working directory
  • 原文地址:https://www.cnblogs.com/globalcoding/p/12824765.html
Copyright © 2011-2022 走看看