spring AOP和事务相关知识

SpringAOP介绍

什么是AOP

AOP:Aspect Oriented Programming,面向切面编程,可以说是OOP(Object Oriented Programming,面向对象编程)的补充和完善。

OOP引入封装、继承、多态等概念来建立一种对象层次结构

AOP则利用一种称为“横切”的技术,剖开对象内部,并将公共行为封装到可重用模块,从而减少重复代码,降低耦合。

AOP的基本概念

  • (1)Aspect(切面):通常是一个类,里面可以定义切入点和通知
  • (2)JointPoint(连接点):程序执行过程中明确的点,一般是方法的调用
  • (3)Advice(通知):AOP在特定的切入点上执行的增强处理,有before,after,afterReturning,afterThrowing,around
  • (4)Pointcut(切入点):就是带有通知的连接点,在程序中主要体现为书写切入点表达式
  • (5)AOP代理:AOP框架创建的对象,代理就是目标对象的加强。Spring中的AOP代理可以使JDK动态代理,也可以是CGLIB代理,前者基于接口,后者基于子

用通俗的语言来描述AOP术语: 切面是指封装横切到系统功能的类,包含通知和切点 切点定义切面插入在哪些方法上,确定切面使用范围 通知定义了切点处所要执行的程序代码以及执行时机 连接点是在应用执行过程中满足切点范围的具体的点 织入是把切面插入到目标对象上

通知方法

前置通知,使用aop:before标签,在方法之前执行

后置通知,使用aop:after标签,在方法之后执行,无论方法内部是否抛出异常

后置返回通知,使用aop:after-returning标签,在方法之后执行并且方法内部不能抛出异常

后置异常通知,使用aop:after-throwing标签,在方法内部抛出异常时执行

环绕通知,使用aop:around标签,在方法之前和之后都执行

Spring AOP的两种实现方式

通过Spring API实现AOP

引入依赖

使用Spring自带的AOP

Spring API相关接口

前置通知:MethodBeforeAdvice

后置通知:AfterReturningAdvice

环绕通知:MethodInterceptor

异常抛出通知:ThrowAdvice

创建一个service类

创建applicationContext.xml

执行方法

执行结果

使用注解实现

执行结果

Spring AOP实现原理

Spring AOP是通过动态代理来实现,主要是JDK动态代理和CGLIB代理两种代理模式

JDK动态代理:Spring AOP的首选方法。 每当目标对象实现一个接口时,就会使用JDK动态代理。目标对象必须实现接口

CGLIB代理:如果目标对象没有实现接口,则可以使用CGLIB代理。

代理模式

由于某些原因需要给某对象提供一个代理以控制对该对象的访问。这时,访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象和目标对象之间的中介

JDK动态代理

优点

JDK动态代理是JDK原生的,不需要任何依赖即可使用;

通过反射机制生成代理类的速度要比CGLib操作字节码生成代理类的速度更快;

缺点

如果要使用JDK动态代理,被代理的类必须实现了接口,否则无法代理;

JDK动态代理无法为没有在接口中定义的方法实现代理,假设我们有一个实现了接口的类,我们为它的一个不属于接口中的方法配置了切面,Spring仍然会使用JDK的动态代理,但是由于配置了切面的方法不属于接口,为这个方法配置的切面将不会被织入。

JDK动态代理执行代理方法时,需要通过反射机制进行回调,此时方法执行的效率比较低;

CGLIB代理

CGLIB是一个功能强大,高性能的代码生成包。它为没有实现接口的类提供代理,为 JDK 的动态代理提供了很好的补充。

事务

1.事务的概念

事务是数据库操作的最小工作单元,是作为单个逻辑工作单元执行的一系列操作,这些操作作为一个整体一起向系统提交,要么都执行、要么都不执行;事务是一组不可再分割的操作集合。

2.事务的基本事务属性

传播行为(propagation behavior):当事务方法被另一个事务方法调用时,必须指定事务应该如何传播。Spring定义了七种传播行为

隔离级别(isolation level):定义了一个事务可能受其他并发事务的影响程度。多个事务并发运行,经常会操作相同的数据来完成各自的任务,可能会出现脏读,不可重复读和幻读的问题。隔离级别有四种

是否只读(isReadOnly):如果一个方法内都是对数据库的select操作,那么可以设置方法事务为只读,数据库也会对该事务进行特定的优化。只读事务内不能有insert、update、delete的操作事务超时(timeout(默认是False)

):事务可能设计对后端数据库的锁定,所以长时间的事务运行会不必要的占用数据库资源,设置事务超时时间可以及时释放资源

3.事务的ACID原则

事务具有4个基本特性:原子性、一致性、隔离性、持久性。也就是我们常说的ACID原则。

原子性

一个事务已经是一个不可再分割的工作单位。事务中的全部操作要么都做;要么都不做

一致性

事务的执行使数据从一个状态转换为另一个状态,但是对于整个数据的完整性保持稳定。

隔离性 

事务允许多个用户对同一个数据进行并发访问,而不破坏数据的正确性和完整性。同时,并行事务的修改必须与其他并行事务的修改相互独立。

持久性

一个事务一旦提交,它对数据库中数据的改变会永久存储起来。其他操作不会对它产生影响

4.Spring事务API介绍

(1) PlatformTransactionManager【事务平台管理器】

  • 是一个接口,定义了获取事务【getTransaction】、提交事务【commit】、回滚事务【rollback】的接口

(2)TransactionDefinition【事务定义信息】

  • 是一个接口,定义了事务隔离级别、事务传播行为、事务超时时间、事务是否只读

5.事务管理级别

(1)为什么要事务隔离

脏读

在一个事务中读取到了另外一个事务修改的【未提交的数据】,而导致多次读取同一个数据返回的结果不一致 (必须要解决的)

不可重复读

在一个事务中读取到了另外一个事务修改的【已提交的数据】,而导致多次读取同一个数据返回的结果不一致

幻读

一个事务读取了几行记录后,另一个事务插入一些记录,幻读就发生了。再后来的查询中,第一个事务就会发现有些原来没有的记录

(2)Spring事务隔离级别

隔离级别由低到高【读未提交】=>【读已提交】=>【可重复读】=>【序列化操作】

6.事务传播行为

指的就是当一个事务方法被另一个事务方法调用时,这个事务方法应该如何进行。

7.事物的管理方式

编程式事务管理 :编程式事务管理是通过编写代码实现的事务管理。可以根据需求规定事务从哪里开始,到哪里结束,拥有很高的灵活性。但是这种方式,会使业务代码与事务规则高度耦合,难以维护,因此我们很少使用这种方式对事务进行管理。

声明式事务管理: 采用声明的方式来处理事务,可以通过 2 种方式实现,分别是 XML和注解方式。Spring 在进行声明式事务管理时,底层使用了 AOP 。事务管理不侵入开发的组件。

具体实现(模拟银行转账业务)

1.创建一个数据库

SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for `account`
-- ----------------------------
DROP TABLE IF EXISTS `account`;
CREATE TABLE `account` (
  `id` int NOT NULL AUTO_INCREMENT,
  `name` varchar(11) COLLATE utf8mb4_general_ci NOT NULL,
  `money` decimal(10,2) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
-- ----------------------------
-- Records of account
-- ----------------------------
INSERT INTO `account` VALUES ('1', 'cmf', '2000.00');
INSERT INTO `account` VALUES ('2', 'lht', '1000.00');

2.导入相关依赖

<dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.3.8</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.3.8</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.3.8</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.4</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.33</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.6</version>
        </dependency>
    </dependencies>

3.创建一个实体类

4.创建Dao

5.创建一个Dao的实现类

6.创建一个Service

7.创建一个Service的实现类

8.编写jdbc.properties

9.基于注解方式

(1)Spring配置类SpringConfig

(2)配置类JdbcConfig

(3)业务层实现类修改代码

(4)测试

结果

扩展

只需要在Service实现类中做些变更,不用在JdbcConfig配置类中配置事务管理器,也可以实现事务管理

除了通过注解的方式,还可以通过XML的的方式实现事务的管理,如下配置

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值