学习笔记13——Spring整合Mybatis、junit、AOP、事务

学习笔记系列开头惯例发布一些寻亲消息

链接:https://baobeihuijia.com/bbhj/

Mybatis - Spring(使用第三方包new一个对象bean)

  • 原始的Mybatis与数据库交互【通过sqlmapconfig来配置和连接】

    • 初始化SqlSessionFactory
    • 获得连接
    • 获取数据层接口
      • 需要一个类与数据中的数据进行匹配
      • 用注解形式进行增删改查
    • 关闭连接
  • 使用第三方包Spring-Mybatis,将mybatis改为spring的模式,不要再类内new SqlSessionFactory,而是把mybatis当作容器的对象可以用

    • 引入mybatis-spring第三方包来帮助整合,在注解方法中,如果要用第三方包则需要新建一个config然后在这个类中手动new一个bean
    • 通过Bean生成一个SqlSessionFactoryBean对象(加入扫描类型的包),与数据源建立连接
    • 生成MapperScannerConfigurer对象,获取数据层
    • 因此就可以通过注解的方式生成对象调用数据库了
    public class MybatisConfig {
        //定义bean,SqlSessionFactoryBean,用于产生SqlSessionFactory对象
        @Bean
        public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource){
            SqlSessionFactoryBean ssfb = new SqlSessionFactoryBean();
            ssfb.setTypeAliasesPackage("com.itheima.domain");
            ssfb.setDataSource(dataSource);
            return ssfb;
        }
        
        //定义bean,返回MapperScannerConfigurer对象
        @Bean
        public MapperScannerConfigurer mapperScannerConfigurer(){
            MapperScannerConfigurer msc = new MapperScannerConfigurer();
            msc.setBasePackage("com.itheima.dao");
            return msc;
        }
    }
    

Junit-Spring(添加注解)

  • Junit与spring的整合(在测试类上添加注解,然后在类内直接@Autowired就可以将容器的对象引入测试)

    //设置类运行器
    @RunWith(SpringJUnit4ClassRunner.class)
    //设置Spring环境对应的配置类
    @ContextConfiguration(classes = SpringConfig.class)
    

AOP-Spring

新建一个class作为component,并且标记该类不是普通的类,是AOP类,打开config的AOP扫描

一般用在service拦截判断,拦截一批处理一批,然后将正确数据传入数据层

  • AOP:面向切面编程,通过调用第三方包AOP,不需要new对象,只需要新建一个component类,并且通过@EnableAspectJAutoProxy和@Aspect保证config知道有AOP并且知道哪个是AOP,从而调度对象代码执行时,切入执行通知

    • 在不惊动原始设计的基础上为其增强功能

      • 连接点:运行过程的任意方法
      • 切入点:多个方法
      • 通知:在切入点指定的操作,即共性功能
      • 切面:通知与切入点的绑定
    • 在spring-config中添加
      @EnableAspectJAutoProxy
      
      @Component
      //设置当前类为切面类类
      @Aspect
      public class MyAdvice {
          //设置切入点,要求配置在方法上方
          @Pointcut("execution(void com.itheima.dao.BookDao.update())")
          private void pt(){}
      
          //设置在切入点pt()的前面运行当前操作(前置通知)
          // @Before("pt()")
          public void method(){
              System.out.println(System.currentTimeMillis());
          }
      }
      
  • AOP工作流程

    • spring容器启动
    • 容器开启AOP检测
    • 扫描component的时候扫描Aspect
    • 读取所有的绑定通知的切入点
      • 匹配成功:创建原始对象(被代理的原始对象称为目标对象)的代理对象bean进入容器
      • 匹配失败:自定义对象以及引入的对象(如mybatis)bean加入到容器
  • AOP切入点描述表达式

    execution(返回值 方法路径 (参数))
    // 采用通配符来为一批方法设置切入点
    
    // 技巧
    切入点一般描述到接口
    返回值:对于增删改方法用精准类型加速匹配,对于查询类使用*通配快速匹配
    

    学习笔记13——Spring整合Mybatis、junit、AOP、事务_第1张图片

  • AOP通知类型

    • 前置通知Before

    • 后置通知After

    • 环绕Around【ProceedingJoinPoint pjp】

      // 拦截后需要return
      // 要抛出异常,不然就相当于执行原始代码出现问题,但是在这里将问题吃掉了
      
          @Around("pt2()")
          public Object aroundSelect(ProceedingJoinPoint pjp) throws Throwable {
              System.out.println("around before advice ...");
              //表示对原始操作的调用
              Integer ret = (Integer) pjp.proceed();
              System.out.println("around after advice ...");
              return ret;
          }
      
    • AfterReturning

    • AfterThrow

  • AOP通知拿参数

    • 都可以拿到参数,可被修改

      JoinPoint jp
      Object[] args = jp.getArgs();
      System.out.println(Arrays.toString(args));
      
      	public Object around(ProceedingJoinPoint pjp) {
              Object[] args = pjp.getArgs();
              System.out.println(Arrays.toString(args));
              args[0] = 666;
              Object ret = null;
              try {
                  ret = pjp.proceed(args);
              } catch (Throwable t) {
                  t.printStackTrace();
              }
              return ret;
          }
      
    • 返回值

      	// 接返回值
      	@AfterReturning(value = "pt()",returning = "ret")
          public void afterReturning(JoinPoint jp,String ret) {
              System.out.println("afterReturning advice ..."+ret);
      	}
      
      	// 接返回值
      	@Around("pt2()")
          public Object aroundSelect(ProceedingJoinPoint pjp) throws Throwable {
              System.out.println("around before advice ...");
              //表示对原始操作的调用
              Integer ret = (Integer) pjp.proceed();
              System.out.println("around after advice ...");
              return ret;
          }
      
    • 异常

      @Transactional// 接异常
      	@AfterThrowing(value = "pt()",throwing = "t")
          public void afterThrowing(Throwable t) {
              System.out.println("afterThrowing advice ..."+t);
      }
      
      // 接异常
      	@Around("pt2()")
          public Object aroundSelect(ProceedingJoinPoint pjp) throws Throwable {
              System.out.println("around before advice ...");
              //表示对原始操作的调用
              Integer ret = (Integer) pjp.proceed();
              System.out.println("around after advice ...");
              return ret;
          }
      
  • 事务

    【spring在业务层开了一个事务,保证一系列数据操作同成功同失败,用的是mysql的事务原理】

    // 在接口上添加@Transactional
    
    // 定义一个事务管理器
    	@Bean
        public PlatformTransactionManager transactionManager(DataSource dataSource){
            DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
            //第三方需要对象的时候要通过参数
            transactionManager.setDataSource(dataSource);
            return transactionManager;
        }
    
    // 告诉spring要检测注解事务
    @EnableTransactionManagement
    
  • Spring的事务原理:通过使用共同的datasource来开启mysql事务

    • 事务管理员:发起事务方
    • 事务协调员:加入事务方

    学习笔记13——Spring整合Mybatis、junit、AOP、事务_第2张图片

  • 有些异常默认不参与回滚:需要@Transactional的时候手动添加

  • 事务传播行为有七种:REQUIRES_NEW是让该事务协调员不加入到事务管理员,而是自己开一个事务,失败了不会跟着回滚

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    

务方

[外链图片转存中…(img-OBMznC6o-1703559380919)]

  • 有些异常默认不参与回滚:需要@Transactional的时候手动添加

  • 事务传播行为有七种:REQUIRES_NEW是让该事务协调员不加入到事务管理员,而是自己开一个事务,失败了不会跟着回滚

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    

    学习笔记13——Spring整合Mybatis、junit、AOP、事务_第3张图片

你可能感兴趣的:(学习,笔记,spring)