ssm框架

一、spring

1.1 Spring Framework系统架构

Spring Framework是Spring生态圈中最基础的项目,是其他项目的根基

image-20240705190946119

  • Data Access: 数据访问
  • Data Integration: 数据集
  • Web: Web开发
  • AOP:面向切面编程
  • Aspects: AOP思想实现
  • Core Container: 核心容器
  • Test:单元测试与集成测试

image-20240705191151579

1.2 核心概念

  • IoC(Inversion of Control)控制反转

    • 使用对象时,由主动new产生对象转换为由外部提供对象,此过程中对象创建控制权由程序转移到外部,此思想称为控制反转
  • Spring技术对IoC思想进行了实现

    • Spring提供了一个容器,称为IoC容器,用来充当IoC思想中的外部
    • IoC容器负责对象的创建、初始化等一系列工作, 被创建或被管理的对象在IoC容器中统称为Bean
  • DI ( Dependency Injection )依赖注入

    • 在容器中建立bean与bean之间的依赖关系的整个过程, 称为依赖注入

image-20240705192834620

IoC具体实现:

  1. 导入spring坐标,新建spring配置文件applicationContext.xml

  2. 在配置文件中配置bean

    1
    2
    3
    4
    5
    6
    7
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id = "bookDao" class="org.example.dao.impl.BookDaoImpl"/>
    <bean id = "bookService" class="org.example.service.impl.BookServiceImpl"/>
    </beans>
  3. 获取Ioc容器

  4. 获取bean

1
2
3
4
5
6
7
8
9
10
11
public class App2 {
public static void main(String[] args) {
//获取ioc容器
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
//获取bean
BookDao bookDao = (BookDao) ctx.getBean("bookDao");
BookService bookService = (BookService) ctx.getBean("bookService");

bookService.save();
}
}

DI具体实现:

1.删除业务层中new创建的dao对象

2.提供对应的set方法

3.配置dao与service的关系

1
2
3
4
5
6
7
8
<bean id = "bookDao" class="org.example.dao.impl.BookDaoImpl"/>
<bean id = "bookService" class="org.example.service.impl.BookServiceImpl">
<!-- property标签表示配置当前bean的属性-->
<!-- name属性表示配置哪一个 具体的属性(成员属性)-->
<!-- ref属性表示参照哪.个bean-->
<property name="bookDao" ref="bookDao"/>

</bean>

1.3 XML-bean配置

  • bean基础配置

image-20240712211353566

  • bean别名配置

使用name属性配置别名,多个别名使用空格隔开

image-20240712211814742

1
<bean id = "bookDao" name="bookDao2 bookDao3" class="org.example.dao.impl.BookDaoImpl"/>
  • bean作用范围配置

spring创建的bean默认为单例,使用scope属性配置,singleton(单例),prototype(非单例)

image-20240712212001921

  • bean适用对象说明
  • 适合交给容器进行管理的bean
    • 表现层对象
    • 业务层对象
    • 数据层对象
    • 工具对象
  • 不适合交给容器进行管理的bean
    • 封装实体的域对象

1.4 XML-bean实例化

  1. 方法一:构造方法实例化bean

bean本质上就是对象,实例化就是调用的无参构造方法(无论是public还是private)

  1. 方法二:使用静态工厂实例化bean

静态工厂:

1
2
3
4
5
public class OrderDaoFactory {
public static OrderDao getOrderDao() {
return new OrderDaoImpl();
}
}

配置:

1
<bean id="orderDao" class="org.example.factory.OrderDaoFactory" factory-method="getOrderDao" />
  1. 方法三:实例工厂实例化bean

实例工厂:

1
2
3
4
5
public class UserDaoFactory {
public UserDao getUserDao() {
return new UserDaoImpl();
}
}

配置:

1
2
<bean id="userDaoFactory" class="org.example.factory.UserDaoFactory" />
<bean id="userDao" factory-bean="userDaoFactory" factory-method="getUserDao"/>
  1. 方法四:使用factoryBean实例化(方法三改良)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class UserDaoFactoryBean implements FactoryBean<UserDao> {
//替代原始实例工厂中创建对象的方法
@Override
public UserDao getObject() throws Exception {
return new UserDaoImpl();
}

@Override
public Class<?> getObjectType() {
return UserDao.class;
}
}
//单例对象开关
@Override
public boolean isSingleton() {
return FactoryBean.super.isSingleton();
}

配置:

1
<bean id="userDao" class="org.example.factory.UserDaoFactoryBean"/>

1.5 XML-bean生命周期

  1. 提供生命周期控制方法,并写好配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class BookDaoImpl implements BookDao {
private BookDaoImpl() {
System.out.println("bookDaoImpl constructor is running ...");
}

@Override
public void save() {
System.out.println("book dao save ...");
}
//提供给bean初始化的方法
public void init(){
System.out.println("init book dao ...");
}
//提供给bean销毁的方法
public void destory(){
System.out.println("destory book dao ...");
}

}

配置:

使用init-methoddestory-method属性配置

1
<bean id = "bookDao" name="bookDao2 bookDao3" class="org.example.dao.impl.BookDaoImpl" init-method="init" destroy-method="destory"/>
  1. 使用spring提供的接口控制生命周期

实现InitializingBean, DisposableBean接口,实现方法destory()afterPropertiesSet()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class BookServiceImpl implements BookService, InitializingBean, DisposableBean {
//删除业务层中new创建的dao对象
private BookDao bookDao;
@Override
public void save() {

System.out.println("book service save ...");
bookDao.save();
}

public void setBookDao(BookDao bookDao) {
this.bookDao = bookDao;
}
//bean销毁前执行方法
@Override
public void destroy() throws Exception {
System.out.println("destroy book service destroy");
}
//bean初始化方法,在属性设置后执行即setBookDao()方法
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("init book service afterPropertiesSet");
}
}

image-20240713191307952

image-20240713191330775

1.6 XML-依赖注入方式(DI)

  1. setter注入(简单类型,引用类型)
  • 简单类型

写好简单类型的set方法

在配置文件中,bean标签中使用property标签,配置property标签的name属性(与简单类型相同)与value属性(要提供的值)

  • 引用类型

写好引用类型的set方法

在配置文件中,bean标签中使用property标签,配置property标签的name属性(与简单类型相同)与ref属性(参照bean的名称)

1
2
3
4
5
6
7
8
9
10
11
12
<!--    简单类型配置-->
<bean id = "bookDao" name="bookDao2 bookDao3" class="org.example.dao.impl.BookDaoImpl">
<property name="databaseName" value="mysql"></property>
<property name="connectionNumber" value="10"></property>
</bean>
<!-- 引用类型配置-->
<bean id = "bookService" class="org.example.service.impl.BookServiceImpl">
<!-- property标签表示配置当前bean的属性-->
<!-- name属性表示配置哪一个 具体的属性-->
<!-- ref属性表示参照哪.个bean-->
<property name="bookDao" ref="bookDao"/>
</bean>
  1. 构造方法注入(简单类型、引用类型)
  • 简单类型

使用构造器传参,在constructor-arg标签中配置name(与构造器形参一致)、value属性

  • 引用类型

使用构造器传参,在constructor-arg标签中配置name(与构造器形参一致)、ref属性

1
2
3
4
5
6
7
8
9
<!--    简单类型配置-->
<bean id = "bookDao" name="bookDao2 bookDao3" class="org.example.dao.impl.BookDaoImpl">
<constructor-arg name="connectionNumber" value="10"/>
<constructor-arg name="databaseName" value="mysql"/>
</bean>
<!-- 引用类型配置-->
<bean id = "bookService" class="org.example.service.impl.BookServiceImpl">
<constructor-arg name="bookDao" ref="bookDao"></constructor-arg>
</bean>

解耦合改良:

使用type属性表示形参

使用index属性表示形参

image-20240713200800319

1.7 XML-依赖自动装配(引用类型)

  • IoC容器根据bean所依赖的资源在容器中自动查找并注入到bean中的过程称为自动装配
  • 自动装配方式
    • 按类型(常用)
    • 按名称
    • 按构造方法
    • 不启用自动装配
1
<bean id = "bookService" class="org.example.service.impl.BookServiceImpl" autowire="byType">

image-20240713202511703

image-20240713202655829

1.8 XML-集合注入

集合 标签
array property嵌array嵌value(ref)
list property嵌list嵌value(ref)
set property嵌set嵌value(ref)
map property嵌map嵌entry
property property嵌props嵌prop
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<bean id = "bookDao" name="bookDao2 bookDao3" class="org.example.dao.impl.BookDaoImpl" >
<property name="array">
<array>
<value>10</value>
<value>20</value>
<value>30</value>
<value>40</value>
</array>
</property>
<property name="list">
<list>
<value>wei</value>
<value>kkk</value>
<value>yang</value>
</list>
</property>
<property name="set">
<set>
<value>hahh</value>
<value>jjj</value>
<value>jjj</value>
</set>

</property>
<property name="map">
<map>
<entry key="wei" value="666"/>
<entry key="si" value="66"/>
</map>
</property>
<property name="properties">
<props>
<prop key="country">china</prop>
<prop key="province">jiangsu</prop>
</props>
</property>
</bean>

1.9 XML-管理数据源对象

1
2
3
4
5
6
7
8
9
10
11
12
13
<!--    管理DruidDataSource对象-->
<bean id="dataSource1" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/3306"/>
<property name="username" value="root"/>
<property name="password" value="weisiyang"/>
</bean>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"/>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/3306"/>
<property name="user" value="root"/>
<property name="password" value="weisiyang"/>
</bean>

1.9 XML-加载properties文件

  1. 开启context命名空间
1
2
3
4
5
6
7
<beans xmlns="http://www.springframework.org/schema/beans"      xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
">

2.加载properties文件,多个文件location中用,隔开

1
<context:property-placeholder location="jdbc.properties"/>

常用格式:

1
<context:property-placeholder location="classpath*:*.properties"/>

3.使用属性占位符${}读取文件中的属性-

1
2
3
4
5
6
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>

image-20240713222444521

1.10 容器

  1. 创建容器

image-20240713222923143

  1. 获取bean

image-20240713224026641

  1. 容器类层次结构图

image-20240713223938008

2.1 注解开发

  1. 使用@component定义bean
1
2
3
@Component
public class BookDaoImpl implements BookDao {
}
  1. 核心配置文件中通过组件扫描加载bean
1
<context:component-scan base-package="org.example"/>

component衍生注解

image-20240713225743457

2.2 纯注解开发

  1. 使用@Configuration注解设置当前类为配置类

  2. 使用@ComponentScan注解设定扫描路径,多个数据用数组格式

1
2
3
4
@Configuration
@ComponentScan({"org.example.dao","org.example.service"})
public class SpringConfig {
}
  1. 加载配置类初始化容器
1
2
//获取ioc容器
ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);

2.3 注解开发-bean管理

  1. bean作用范围

使用@Scope注解设定某个类

1
2
@Scope("singleton")
@Scope("prototype")

2.bean生命周期

使用@PostConstruct注解设定某个类中的方法为构造方法后初始化方法

1
2
3
4
@PostConstruct
public void init(){
System.out.println("book init ...");
}

使用@PreDestory注解设定某个类中的方法为销毁前方法

1
2
3
4
@PreDestroy
public void destroy(){
System.out.println("book destroy ...");
}

2.4 注解开发-依赖注入

  1. 引用类型:自动装配

使用@Autowired注解设置引用类型自动装配,默认为按类型装配,

可使用@Qualifier注解设置按名称装配(要为配装配的类设置称)

1
2
3
@Autowired
@Qualifier("bookDao2")
private BookDao bookDao;

image-20240714200123026

  1. 简单类型
  • 使用@Value注解为简单类型设置值
1
2
@Value("13")
private int a;
  • 使用配置文件导入值,在配置类中添加@PropertySource(file path)注解(多个文件使用数组形式,不支持*通配符),

    再使用@Value注解与${}占位符注入值

    1
    2
    3
    4
    5
    @Configuration
    @ComponentScan({"org.example.dao","org.example.service"})
    @PropertySource("jdbc.properties")
    public class SpringConfig {
    }
    1
    2
    @Value("${jdbc.driver}")
    private String a;

2.5 注解开发-第三方bean管理、依赖注入

  1. 第三方bean管理

在配置类中定义一个方法用于获取数据源对象,为该方法添加@Bean注解

1
2
3
4
5
6
7
8
9
10
11
public class SpringConfig {
@Bean
DataSource dataSource(){
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName("${jdbc.driverClassName}");
ds.setUrl("${jdbc.url}");
ds.setUsername("${jdbc.username}");
ds.setPassword("${jdbc.password}");
return ds;
}
}

获取数据源对象:

1
2
3
4
5
6
7
8
9
public class App 
{
public static void main( String[] args )
{
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
DataSource dataSource = (DataSource)context.getBean(DataSource.class);
System.out.println(dataSource);
}
}
  • 改良:新建单独配置类,在主配置类中使用@Import(className.Class)导入该类(导入多个类使用数组形式
1
2
3
4
5
6
7
8
9
10
11
public class JdbcConfig {
@Bean
DataSource dataSource(){
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName("${jdbc.driverClassName}");
ds.setUrl("${jdbc.url}");
ds.setUsername("${jdbc.username}");
ds.setPassword("${jdbc.password}");
return ds;
}
}
1
2
3
4
5
6
7
8
@Configuration
@ComponentScan({"org.example.dao","org.example.service"})
@PropertySource("jdbc.properties")
@Import(JdbcConfig.class)

public class SpringConfig {

}
  1. 依赖注入
  • 简单类型
1
2
3
4
5
6
7
8
9
@Value("${jdbc.driverClassName}")
private String className;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
@Bean
  • 引用类型

作为形参会自动装配(按类型

1
2
3
4
5
6
7
8
9
10
11
@Bean
DataSource dataSource(BookDao bookDao){
//bookDao自动装配
System.out.println(bookDao);
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName(className);
ds.setUrl(url);
ds.setUsername(username);
ds.setPassword(password);
return ds;
}

3. XML与注解开发对比

image-20240714204702547

二、Spring整合

1.1Spring整合MyBatis

  1. 导入依赖坐标
1
2
3
4
5
6
7
8
9
10
11
12
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.6</version>
</dependency>


<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.0</version>
</dependency>
  1. 与sqlsessionFactory有关的配置转换成sqlSessionFactory方法来配置

image-20240715000923014

  1. mapper映射转换成Mybatis配置类中MapperScannerConfiguer方法

image-20240715001218816

1.2 Spring整合Junit

  1. 导入依赖坐标
1
2
3
4
5
6
7
8
9
10
11
<dependency>  <groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>

<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
  1. 设置类加载器(SpringJunit4ClassRunner),设置spring上下文配置(SpringContext)
1
2
3
4
5
6
//类加载器
@RunWith(SpringJUnit4ClassRunner.class)
//上下文配置
@ContextConfiguration(classes = SpringConfig.class)
public class AccountServiceTest {
}
  1. 进行测试
1
2
3
4
5
6
7
8
9
10
public class AccountServiceTest {
@Autowired
private AccountService accountService;

@Test
public void TestAccountService() {
System.out.println(accountService.findById(1));

}
}

三 AOP

1.1 AOP简介

  • AOP(Aspect Oriented Programming) 面向切面编程,一种编程范式 ,指导开发者如何组织程序结构
    • 00P(Object 0riented Progr amming)面向对象编程
  • 作用:在不惊动原始设计的基础上为其进行功能增强
  • Spring理念:无入侵式/无侵入式

核心概念:

  • 连接点( JoinPoint ) : 程序执行过程中的任意位置, 粒度为执行方法、抛出异常、设置变量等
    • 在SpringAOP中 ,理解为方法的执行
  • 切入点( Pointcut ) : 匹配连接点的式子(切入点<连接点)
    • 在SpringAOP中 , -个切入点可以只描述一个具体方法,也可以匹配多个方法
      • 一个具体方法: com. itheima . dao包下的BookDao接口中的无形参无返回值的save方法
      • 匹配多个方法:所有的save方法,所有的get开头的方法,所有以Dao结尾的接口中的任意方法,所有带有-个参数的方法
  • 通知( Advice ) : 在切入点处执行的操作,也就是共性功能
    • 在SpringAOP中,功能最终以方法的形式呈现
  • 通知类:定义通知的类
  • 切面( Aspect ) : 描述通知与切入点的对应关系

image-20240715195329840

1.2 AOP入门案例

  1. 导入Aspect坐标
1
2
3
4
5
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>
  1. 写一个通知类,写一个通知,一个切入点

  2. 设置切入点的注解,绑定通知与切入点

    切入点定义依托一个不具有实际意义的方法进行,即无参数,无返回值, 方法体无实际逻辑(如下的pc方法)

  3. 将通知类转为bean,使用@Aspect注解让spring将通知类以aop来处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//4.设置通知类为bean,以便spring管理
@Component
//5.让spring知道该类为Aop切面类
@Aspect

public class MyAdtive {
//1. 切入点
@Pointcut("execution(void org.example.dao.BookDao.update())")
private void pc(){}

//2. 通知
//3. 使用@Before绑定通知与切入点
@Before("pc()")
public void method(){
System.out.println(System.currentTimeMillis());
}
}
  1. 在配置类中打开aop注解开发模式@EnableAspectJAutoProxy
1
2
3
4
5
6
@Configuration
@ComponentScan("org.example")
//6.aop注解开发,自动代理
@EnableAspectJAutoProxy
public class SpringConfig {
}

1.3 AOP工作流程

  1. 工作流程
  1. Spring容器启动
  2. 读取所有切面配置中的切入点
  3. 初始化bean ,判定bean对应的类中的方法是否匹配到任意切入点
    • 匹配失败 ,创建对象
    • 匹配成功 ,创建原始对象(目标对象)的代理对象
  4. 获取bean执行方法
    • 获取bean ,调用方法并执行,完成操作
  1. 核心概念
  • 目标对象( Target ) : 原始功能去掉共性功能对应的类产生的对象,这种对象是无法直接完成最终工作的
  • 代理( Proxy) :目标对象无法直接完成工作,需要对其进行功能回填 ,通过原始对象的代理对象实现

1.4 AOP切入点表达式

  1. 语法格式
  • 切入点:要进行增强的方法
  • 切入点表达式:要进行增强的方法的描述方式

image-20240715211545256

切入点表达式标准格式:动作关键字(访问修饰符 返回值 包名.类/接口名.方法名(参数)异常名)

image-20240715211904474

  • 动作关键字:描述切入点的行为动作, 例如execution表示执行到指定切入点
  • 访问修饰符: public , private等,可以省略
  • 返回值
  • 包名
  • 类/接口名.
  • 方法名
  • 参数
  • 异常名:方法定义中抛出指定异常,可以省略
  1. 切入点表达式通配符:
  • * :单个独立的任意符号,可以独立出现,也可以作为前缀或者后缀的匹配符出现

    image-20240715212208853

  • .. :多个连续的任意符号,可以独立出现,常用于简化包名与参数的书写

    image-20240715212305992

  • +:专用于匹配子类类型

    image-20240715212402743

  1. 书写技巧

image-20240715213409053

1.5 AOP通知类型

  • AOP通知描述了抽取的共性功能, 根据共性功能抽取的位置不同,最终运行代码时要将其加入到合理的位置
  • AOP通知共分为5种类型
    • 前置通知
    • 后置通知
    • 环绕通知(重点)
    • 返回后通知(了解)
    • 抛出异常后通知 (了解)
  1. 前置通知@Before
1
2
3
4
@Before("pc()")
public void before(){
System.out.println("Before Adtive");
}
  1. 后置通知@After
1
2
3
4
@After("pc()")
public void after(){
System.out.println("After Adtive");
}
  1. 环绕通知@Around

无返回值:

1
2
3
4
5
6
7
@Around("pc()")
public void around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("Around Before Adtive");
//原始方法的调用
pjp.proceed();
System.out.println("Around After Adtive");
}

有返回值:

1
2
3
4
5
6
7
8
@Around("pc2()")
public Object around2(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("Around Before Adtive");
//原始方法的调用
Object rej = pjp.proceed();
System.out.println("Around After Adtive");
return rej;
}

注意:

  1. 环绕通知必须依赖形参ProceedingJoinPoint才 能实现对原始方法的调用, 进而实现原始方法调用前后同时添加通知

  2. 通知中如果未使用ProceedingJoinPoint对原始方法进行调用将跳过原始方法的执行

  3. 对原始方法的调用可以不接收返回值 ,通知方法设置成void即可,如果接收返回值,必须设定为Object类型

  4. 原始方法的返回值如果是void类型,通知方法的返回值类型可以设置成void ,也可以设置成Object

  5. 由于无法预知原始方法运行后是否会抛出异常 ,因此环绕通知方法必须抛出Throwable对象

获取原方法信息:

  • Signature对象(执行签名信息)中的方法获取
    • getDeclaringType,获取声明类型(接口名)
    • getName,获取原方法名称
    • getDeclaringType().getName() = getDeclaringTypeName(),获取类型名
1
2
3
4
5
Signature signature = pjp.getSignature();
System.out.println(signature.getDeclaringType());
System.out.println(signature.getName());
System.out.println(signature.getDeclaringType().getName());
System.out.println(signature.getDeclaringTypeName());
  1. 返回后通知@AfterReturning
1
2
3
4
@AfterReturning("pc()")
public void afterReturning(){
System.out.println("afterReturning Adtive");
}
  1. 抛出异常后通知@AfterThrowing
1
2
3
4
@AfterThrowing("pc()")
public void afterThrowing(){
System.out.println("afterThrowing Adtive");
}

1.6 AOP通知获取数据

image-20240715225541359

  1. 获取参数

image-20240715232819825

  1. 获取返回值

image-20240715232845700

  1. 获取异常

image-20240715232918451

1.7 AOP总结

image-20240715233720918

  • 切入点

image-20240715233857472

  • 通知

image-20240715234057350

  • 通知中获取信息

image-20240715234232191

四、Spring事务

1.1 事务简介

  • 事务作用:在数据层保障一系列的数据库操作同成功同失败
  • Spring事务作用:在数据层或业务层保障一系列的数据库操作同成功同失败

image-20240805160833949