深入理解Spring事务和Spring AOP

2018-12-24  本文已影响41人  HelloPeng

什么是AOP编程

  1. Aspect Oriented Programming 面向切面编程
  2. 主要应用场景是日志记录,权限控制,性能监控,事务处理,异常处理等
  3. 主要意图是将日志记录,权限控制,性能监控,事务处理,异常处理等代码从业务逻辑代码中抽取出来,降低耦合性并解决代码复用的问题
  4. 底层实现原理是代理设计模式,可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能.假设把应用程序想成一个立体结构的话,OOP的利刃是纵向切入系统,把系统划分为很多个模块(如: 用户模块,文章模块等等),而AOP的利刃是横向切入系统,提取各个模块可能都要重复操作的部分(如: 权限检查,日志记录等等).由此可见,AOP是OOP的一个有效补充

名词解释

  1. 关注点: 重复代码(如打印日志的代码)
  2. 切面/切面类: 关注点形成的类,将重复代码抽取出来,在运行的时候在业务方法上动态植入
  3. 切入点: 执行目标对象方法,动态植入切面代码(可以通过切入点表达式,指定拦截哪些类的哪些方法;给指定的类在运行的时候植入切面类代码)

AOP底层实现原理

代理的分类:

静态代理和动态代理

静态代理和动态代理的区别:

静态代理是静态定义代理类(需要手写代理类);动态代理是动态生成代理类(虚拟生成代理类)

动态代理分为:

jdk动态代理和cglib动态代理

jdk动态代理和cglib的区别:

jdk是基于反射机制实现的;
cglib是基于ASM字节码包装的一个类库(性能比反射要高一些)(ASM是一个java字节码操控框架,它能被用来动态生成类或者增强既有类的功能.ASM可以直接产生二进制class文件,也可以在类被加载进java虚拟机之前动态改变类的行为.)

  1. AOP实现原理: 静态代理和动态代理

  2. 什么是静态代理: 由程序员创建或工具生成代理类的源码,再编译代理类.所谓静态也就是在程序运行前就已经存在代理类的字节码文件,代理类和委托类的关系在运行前就确定了.

    //接口
    public interface IUserDao {
        void save();
    }
    
    //被代理类
    public class UserDaoImpl implements IUserDao {
    
        @Override
        public void save() {
            System.out.println("假装把数据入库了...");
        }
    }
    
    //代理类
    public class UserDaoProxy implements IUserDao {
        private IUserDao target;
    
        public UserDaoProxy(IUserDao userDao) {
            this.target = userDao;
        }
    
        @Override
        public void save() {
            System.out.println("开启事务...");
            target.save();
            System.out.println("提交事务...");
        }
    }
    
  3. 什么是动态代理: 代理类不需要实现接口,动态的在内存中构建代理对象(需要我们指定创建代理对象/目标对象实现的接口的类型)

AOP编程使用

  1. 注解版本实现AOP
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy> 开启事物注解权限

    @Component //交给Spring来处理
    @Aspect    //指定一个类为切面类
    public class AopLog {
        // 前置通知
        @Before("execution(* com.pliu.service.UserService.add(..))")
        public void begin() {
            System.out.println("前置通知");
        }
    
        // 后置通知
        @After("execution(* com.pliu.service.UserService.add(..))")
        public void commit() {
            System.out.println("后置通知");
        }
    
        // 运行通知
        @AfterReturning("execution(* com.pliu.service.UserService.add(..))")
        public void returning() {
            System.out.println("运行通知");
        }
    
        // 异常通知
        @AfterThrowing("execution(* com.pliu.service.UserService.add(..))")
        public void afterThrowing() {
            System.out.println("异常通知");
        }
    
        // 环绕通知
        @Around("execution(* com.pliu.service.UserService.add(..))")
        public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
            System.out.println("环绕通知开始");
            proceedingJoinPoint.proceed();
            System.out.println("环绕通知结束");
        }
    
    }
    
    
  1. xml版本实现AOP(不好意思,感觉麻烦懒得写,如有必要还请百度吧)

Spring事务使用

  1. 事务基本特性

    ⑴ 原子性(Atomicity)
      原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚,因此事务的操作如果成功就必须要完全应用到数据库,如果操作失败则不能对数据库有任何影响。

    ⑵ 一致性(Consistency)
     一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态。
      拿转账来说,假设用户A和用户B两者的钱加起来一共是5000,那么不管A和B之间如何转账,转几次账,事务结束后两个用户的钱相加起来应该还得是5000,这就是事务的一致性。

    ⑶ 隔离性(Isolation)
      隔离性是当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。
      即要达到这么一种效果:对于任意两个并发的事务T1和T2,在事务T1看来,T2要么在T1开始之前就已经结束,要么在T1结束之后才开始,这样每个事务都感觉不到有其他事务在并发地执行。

    ⑷ 持久性(Durability)
      持久性是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。
    例如我们在使用JDBC操作数据库时,在提交事务方法后,提示用户事务操作完成,当我们程序执行完成直到看到提示后,就可以认定事务以及正确提交,即使这时候数据库出现了问题,也必须要将我们的事务完全执行完成,否则就会造成我们看到提示事务处理完毕,但是数据库因为故障而没有执行事务的重大错误。

  1. 事务控制分类
上一篇 下一篇

猜你喜欢

热点阅读