首页 > 其他分享 >Spring学习——SpringAOP

Spring学习——SpringAOP

时间:2024-10-13 21:20:46浏览次数:10  
标签:事务 Spring 代理 切点 学习 import SpringAOP org 方法

0. IOC思想(DI)

1. 关键注解
	
	@Repository
	public class DeptDaoImpl1 implements DeptDao{}
	
	@Repository
	@Primary
	public class DeptDaoImpl2 implements DeptDao{}
	
	@Service
	public class DeptServiceImpl implements DeptService{
	
		@Autowired
		@Qulifier("deptDaoImpl2")
		private DeptDao deptDao;
	}

2. 创建对象
	自定义对象:@Repository  @Service  @Controller  @Component  
	第三方对象:@Bean  @Configuration

3. 对象作用域@Scope
	单例:只有一个, 默认容器启动,对象创建(@Lazy延迟到第一次获取)
	多例:每次获取,创建一个新的

4. 单元测试
	@RunWith(运行器)
	@ContextConfiguration(classes=)

日志功能

需求:在业务层类中的方法中打印日志,记录方法执行前后以及方法发生异常的时间点

基本方式实现

导入初始工程

在这里插入图片描述

添加日志功能

修改DeptServiceImpl,添加日志功能

在这里插入图片描述

测试

在这里插入图片描述

分析代码问题

目前代码存在两个问题

  1. 代码耦合性高:业务代码和日志代码耦合在了一起
  2. 代码复用性低:日志代码在每个方法都要书写一遍

jdk动态代理

在这里插入图片描述

复制工程

在这里插入图片描述

准备目标类

目标类指的是要被代理的类

在这里插入图片描述

准备增强类

增强类指的是要给被代理类添加的功能

在这里插入图片描述

创建代理对象

在测试类中,使用JDK技术创建代理对象,然后调用方法

在这里插入图片描述

cglib动态代理

CGLIB(Code Generation )动态代理利用ASM字节码操作框架在运行时生成代理类,它通过继承的方式代理目标对象,因此可以代理没有实现接口的类。

在这里插入图片描述

复制工程

在这里插入图片描述

删除接口

删除DeptService接口,并删除实现类中对接口的实现

在这里插入图片描述

创建代理对象

package com.itheima.test;

import com.itheima.config.SpringConfig;
import com.itheima.log.Logger;
import com.itheima.service.impl.DeptServiceImpl;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.InvocationHandler;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import java.lang.reflect.Method;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfig.class)
public class DeptServiceTest {

    @Autowired
    private DeptServiceImpl deptServiceImpl;

    @Autowired
    private Logger logger;

    @Test
    public void test1() {
        //1. 准备目标对象(deptService就是)

        //2. 编写增强逻辑
        //注意: 这个InvocationHandler是org.springframework.cglib.proxy.InvocationHandler提供的
        InvocationHandler invocationHandler = new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                Object res = null;

                logger.m1();
                try {
                    res = method.invoke(deptServiceImpl,args);
                }catch (Exception e){
                    logger.m3();
                }
                logger.m2();

                return res;
            }
        };

        //3. 创建代理对象
        DeptServiceImpl proxyInstance = (DeptServiceImpl) Enhancer.create(DeptServiceImpl.class, invocationHandler);

        //4. 调用代理对象的方法
        proxyInstance.findAll();
    }
}

小结

首先明确在创建代理实现类时,jdk的速度要高于cglib,所以选择的时候:

当被代理类有接口的时候,使用jdk动态代理;当被代理类没有接口的时候,使用cglib动态代理

不同点:

在这里插入图片描述

总结

在这里插入图片描述

当核心业务(保存)和增强业务(日志)同时出现时,我们可以在开发时对他们分别开发,运行时再组装在一起(使用动态代理的方式)。

这样做的好处是:

  1. 逻辑清晰:开发核心业务的时候,不必关注增强业务的代码
  2. 代码复用性高:增强代码不用重复书写

这就是一种 AOP ( 面向切面编程 ) 的思想,它的目的就是在不修改源代码的基础上,对原有功能进行增强。

我的总结: 开发阶段分别开发,运行阶段组装运行

AOP

AOP介绍

AOP( 面向切面编程 )是一种思想,它的目的就是在不修改源代码的基础上,对原有功能进行增强。

在这里插入图片描述

SpringAOP是对AOP思想的一种实现,Spring底层同时支持jdk和cglib动态代理。

Spring会根据被代理的类是否有接口自动选择代理方式:

  • 如果有接口,就采用jdk动态代理
  • 如果没接口,就采用cglib的方式

在AOP中有一些核心概念,需要大家了解

* 目标对象(Target)
	被代理的对象

* 连接点(JoinPoint)
	目标对象中得所有方法

* 切入点(PointCut)
	目标对象中得要进行功能增强那部分方法

* 增强 (Advice 通知)
	一个具体增强功能(增强对象  增强方法)

* 切面 (Aspect)
	切面是一种描述,描述的是: 哪个增强方法   加入到了  哪个切点  的   什么位置
	增强方法和切点方法的执行顺序

在这里插入图片描述

入门案例

使用SpringAop完成在业务层类中的方法上打印日志

创建模块,导入依赖

在这里插入图片描述

    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.26</version>
        </dependency>
        
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.3.6</version>
        </dependency>

        <!--切点表达式解析坐标-->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.7</version>
        </dependency>

        <!--测试-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.3.6</version>
        </dependency>
    </dependencies>

创建实体类

创建业务层接口和实现类

在这里插入图片描述

创建日志类

在这里插入图片描述

配置切面

我们需要把切面相关的内容配置在这种增强类中

在这里插入图片描述

创建配置类

在这里插入图片描述

单元测试

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfig.class)

在这里插入图片描述

通知类型

四大通知

四大通知描述的就是增强方法在切点方法的什么位置上执行

- 前置通知(before):增强方法在切点运行之前执行
- 返回后通知(after-returning):增强方法在某切点正常完成后执行的通知,不包括抛出异常的情况
- 异常后通知(after-throwing):增强方法在某切点抛出异常退出时执行的通知
- 后置通知(after):增强方法在某切点退出的时候执行的通知(不论是正常返回还是异常退出)
try{
	前置通知(before)
       
	//切点执行位置
       
	返回后通知(after-returning)
}catch(Execption e){
	异常后通知(after-throwing)
}finally{
	后置通知(after)
}

① 添加通知方法

在这里插入图片描述

② 测试

在这里插入图片描述

环绕通知

它是一种特殊的通知,他允许以编码的形式实现四大通知

① 添加通知方法

在这里插入图片描述

② 测试

在这里插入图片描述

切点表达式

切点表达式用于挑选切点

execution

execution() :指定一组规则来匹配某些类中的方法,匹配中的就是切点

* 代表一个或多个位置
.. 代表0个或多个位置

在这里插入图片描述

@annotation

@annotation:指定一个注解,凡是标有此注解的方法都是切点

① 自定义注解

在这里插入图片描述

② 在需要作为切点的方法上添加注解
在这里插入图片描述

③ 设置切点表达式

在这里插入图片描述

④ 测试

在这里插入图片描述

记录日志详情

在这里插入图片描述

事务管理

事务回顾

事务是一组操作的集合,它是一个不可分割的工作单位,这些操作 要么同时成功,要么同时失败。

开启事务(一组操作开始前,开启事务):start transaction / begin ;

提交事务(这组操作全部成功后,提交事务):commit ;

回滚事务(中间任何一个操作出现异常,回滚事务):rollback ;

转账案例

添加账户表

-- 创建账户表,并且添加两条测试数据
create table account (
                         id int primary key auto_increment,
                         name varchar(32),
                         balance float
);
insert into account (name, balance) VALUES ('A', 1000), ('B', 1000);

导入工程

在这里插入图片描述

添加持久层代码

在Mapper接口中添加加钱和减钱的方法

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

添加业务层代码

在Service接口和实现类中添加转账方法

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

测试

在测试类中添加转账方法

在这里插入图片描述

事务管理

注解:@Transactional

位置:业务(service)层的方法上、类上、接口上

作用:将当前方法交给spring进行事务管理,方法执行前,开启事务;成功执行完毕,提交事务;出现异常,回滚事务

配置事务管理器

在配置类中配置事务管理器,并开启声明式事务

在这里插入图片描述

添加事务注解

在转账方法上添加@Transactional注解,注意方法中要模拟异常

在这里插入图片描述

测试

在测试方法中对转账方法进行测试

在这里插入图片描述

事务属性

rollbackFor

默认情况下,只有出现 RuntimeException 才回滚异常,rollbackFor属性用于控制让非运行时异常也回滚。

在这里插入图片描述

propagation

propagation称为事务传播行为,表示当一个事务方法被另一个事务方法调用时,应该如何进行事务控制

在这里插入图片描述

Spring支持通过配置的形式来实现7种事务传播行为,我们需要掌握其中的前两种

属性值含义
REQUIRED【默认值】需要事务,有则加入,无则创建新事务
REQUIRES_NEW需要新事务,无论有无,总是创建新事务
SUPPORTS支持事务,有则加入,无则在无事务状态中运行
NOT_SUPPORTED不支持事务,在无事务状态下运行,如果当前存在已有事务,则挂起当前事务
MANDATORY必须有事务,否则抛异常
NEVER必须没事务,否则抛异常
NESTED如果一个活动的事务存在,则运行在一个嵌套的事务中。如果没有活动事务, 则开启一个新的事务。
内层事务依赖于外层事务。外层事务失败时,会回滚内层事务所做的动作。
而内层事务操作失败并不会引起外层事务的回滚。

建新事务 |
| REQUIRES_NEW | 需要新事务,无论有无,总是创建新事务 |
| SUPPORTS | 支持事务,有则加入,无则在无事务状态中运行 |
| NOT_SUPPORTED | 不支持事务,在无事务状态下运行,如果当前存在已有事务,则挂起当前事务 |
| MANDATORY | 必须有事务,否则抛异常 |
| NEVER | 必须没事务,否则抛异常 |
| NESTED | 如果一个活动的事务存在,则运行在一个嵌套的事务中。如果没有活动事务, 则开启一个新的事务。
内层事务依赖于外层事务。外层事务失败时,会回滚内层事务所做的动作。
而内层事务操作失败并不会引起外层事务的回滚。 |

标签:事务,Spring,代理,切点,学习,import,SpringAOP,org,方法
From: https://blog.csdn.net/qq_73643693/article/details/142904441

相关文章

  • 两小时学会使用dubbo(直接API、spring、注解、springboot)
    最近上新的项目中需要用到dubbo,于是我决定温故知新,决定分享一下Dubbo在各种环境下的使用方式,本篇文章让你两小时就能学会使用dubbo什么是DubboDubbo是一个分布式、高性能、透明化的RPC服务框架,提供服务自动注册、自动发现等高效服务治理方案,可以和Spring框架无缝集成。Dub......
  • 两小时学会使用dubbo(直接API、spring、注解、springboot)
    最近上新的项目中需要用到dubbo,于是我决定温故知新,决定分享一下Dubbo在各种环境下的使用方式,本篇文章让你两小时就能学会使用dubbo什么是DubboDubbo是一个分布式、高性能、透明化的RPC服务框架,提供服务自动注册、自动发现等高效服务治理方案,可以和Spring框架无缝集成。Dubbo最常......
  • 2024-2025第一学年 20241410苏尚君《计算机基础与程序设计》第三周学习总结
    这个作业属于哪个课程(2024-2025-1-计算机基础与程序设计)这个作业要求在哪里(2024-2025-1计算机基础与程序设计第三周作业这个作业的目标门电路,组合电路,逻辑电路,冯诺依曼结构作业正文教材学习内容总结一、门定义:“门”通常指的是逻辑门(LogicGates),这是构......
  • 深度学习神经网络笔记--卷积神经网络
    为什么要用卷积捕捉特征,如文末的图)不受位置影响(左右,前后,上下)可以参考下图:卷积操作可移动的小窗口与图像数据逐元素相乘后相加小窗口是滤波器,卷积核,(权重矩阵)需要注意的问题:stride:步长卷积核的个数:决定输出的depth,卷积核个数填充值zerp-padding:外圈补0......
  • Springboot整合Mybatis
    1、创建springboot项目2、勾选mysql驱动和web驱动3、pom.xml导入相关依赖<!--MyBatisPlus启动器--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId>&l......
  • 2024-2025 20241313刘鸣宇《计算机基础与程序设计》第三周学习总结
    1.阅读《C语言程序设计》,对有疑问的地方寻找AI进行解答2.3.《计算机科学概论》学习总结(1)第二章学习了不同进制(二进制,十进制,八进制,十六进制)之间的转换学习了其他技术系统中的运算规则(2)第三章1.信息与数据的区别:信息是数据的一种2.为何进行数据压缩:网络具有固定的带宽限制,压......
  • 设计模式学习整理
    学习参考:重构大师创建型模式创建型模式提供了创建对象的机制,能够提升已有代码的灵活性和可复用性。工厂方法模式在父类中提供一个创建对象的方法,允许子类决定实例化对象的类型;实现方式:使用特殊的工厂方法代替对于对象构造函数的直接调用(即使用new运算符),对象仍将通......
  • 2024-2025-1 20241423 《计算机基础与程序设计》第3周学习总结
    作业信息这个作业属于哪个课程<班级的链接>(如2024-2025-1-计算机基础与程序设计)这个作业要求在哪里2024-2025-1计算机基础与程序设计第三周作业这个作业的目标学习《C语言程序设计》第二章并完成云班课测试。自学《计算机科学概论》第2章,第3章并完成云班课测试......
  • 2024-2025-1 20241312 《计算机基础与程序设计》第3周学习总结
    |这个作业属于哪个课程|https://edu.cnblogs.com/campus/besti/2024-2025-1-CFAP|这个作业要求在哪里|https://www.cnblogs.com/rocedu/p/9577842.html#WEEK03|这个作业的目标|数字分类与计数法位置计数法进制转换模拟数据与数字数据压缩与解压数字化信息安全|作业正文|h......
  • 基于SpringBoot+Vue的校园互助任务平台设计和实现(源码+lw+部署+讲解)
    详细视频演示请联系我获取更详细的演示视频具体实现截图技术可行性分析经过调研与分析,我认为使用SpringBoot、Vue和MySQL构建本系统具有很高的技术可行性。具体而言,SpringBoot作为轻量级的Java开发框架,能够快速搭建和简化配置,提高开发效率和降低维护成本;Vue作......