Spring框架
Spring框架
Spring复习
1.了解Spirng
spirng->spring mvc ->spring boot ->spring cloud

层层递进–

2.IOC -Di 了解
由分层解耦引出的依赖注入 以及依赖反转

如图 ->当我们想更改对象 BookDaoImp12 名字时候->时 ->所有业务代码都需要改动改动过大->
Ioc->控制反转
使用对象–由主动new-改为外部提供对象->对象控制器转移到外部
对此-spring提供容器->ioc容器 ->提供了对象的创建和管理
依赖注入

IOC->容器管理Bean->容器管理bookdaoimpl
DI->将具有依赖关系的Bean进行关系绑定->例如上面的bookdao->与bookdaoimpl进行绑定 Spring利用依赖注入机制来处理这些Bean之间的依赖关系,从而实现对象之间的松耦合。
3.加入IOC 容器
1.配置Bean

2.获取Bean

当我们配置bean的时候–容器内就保存了我们的对象地址->单例->谁需要就给予
2.依赖注入



set容器执行->最后还是容器将Bean给予了
spring->编译 –自动找set 依赖方法注入
4.Bean配置



spring->默认的Bean是单例的
如果需要多例 就需要修改配置

为什么bean要单例–
开对象->耗费内存
由于是单例->需要改变的数据就不能加入spring管理->除非开多例
5.Bean实例化
1.ioc过程

给接口内->一个构造->通过xml解析出 需要构造的对象->通过反射 ->创建出对象返回->默认单例
通过类名动态加载类的方法
在使用 Class.forName() 方法时,情况会根据加载的类是否已存在而有所不同:
- 类已存在:
- 如果使用
Class.forName()加载的类在类路径中已经存在,则会返回对应的 Class 对象,而不会创建新的对象。这意味着它只是获取已加载类的引用,不会触发类的初始化和实例化。
- 如果使用
- 类不存在:
- 如果要加载的类在类路径中不存在,则会抛出
ClassNotFoundException异常,而不会创建新的类对象。在这种情况下,不会创建新的类对象,因为类根本就没有被加载到内存中
- 如果要加载的类在类路径中不存在,则会抛出
2.工厂模式
工厂模式 ->由一个类中的静态方法->返回对象的引用
1 | |
createInstance() 是静态工厂方法,负责返回 MyService 类型的对象。
在 Spring 配置文件中使用 <bean> 标签指定静态工厂方法:
1 | |
Java 注解配置静态工厂方法
1 | |
3.实例工厂-
1 | |
Spring 配置文件(applicationContext.xml)中,通过 <bean> 标签配置实例工厂:
1 | |
获取bean
1 | |
Spring 容器首先会创建 MyServiceFactory 的实例,然后调用其 createInstance 方法来创建 MyService 实例。
Java 注解配置实例工厂方法
//多了一步-先获取到实例工厂bean才能够注入
1 | |
FactoryBean
在 Spring 框架中,FactoryBean 是一个特殊的接口,用于自定义 Bean 的创建逻辑
1 | |

指定类-扫描
Spring 容器会创建一个 CarFactoryBean 的实例,并调用它的 getObject() 方法来获取 Car 对象。
1 | |
6.Bean生命周期
1.生命周期配置
1.配置法

2.接口法


2.bean销毁时间
为了体现生命周期->我们提前销毁bean

7.依赖注入
1.了解依赖注入
有Bean关系的类进行自动注入 —向类传递数据方式-set 传递 –构造传参
参数–引用类型和简单类型
2.引用注入
引用注入 是指将一个对象作为另一个对象的属性注入。例如,在一个类中注入另一个类的实例。在 XML 配置或基于注解的方式中,都可以实现引用注入。
引用注入是指将一个 Bean 注入到另一个 Bean 中,这个 Bean 可以通过构造器、Setter 方法、或其他方式注入。引用注入强调的是一种引用关系**。
Person 类需要 Address 类的实例。
1 | |
1 | |
Person 类依赖于 Address 类,即 Person 拥有一个 Address 类型的属性。我们可以通过 Spring 配置文件来实现引用注入。
XML 配置引用注入
1 | |
基于注解
1 | |
3.setter注入
Setter 注入 是一种通过提供 setter 方法来实现依赖注入的方式
Setter 注入通常用于将简单数据类型(如 String、int)或引用类型注入到 Bean 中。在 XML 配置中使用 <property> 标签来定义:
<property> 标签的 name 属性表示要注入的属性名称,value 属性表示简单数据类型的值,ref 属性表示对其他 Bean 的引用。
1 | |
1 | |
4.构造器注入



4.依赖注入方式选择

5.依赖自动装配
IOC容器根据bean所依赖的资源在容器中自动查找并注入到bena的过程称为自动装配
1.按类型
2.按名称
3.按构造方法
4.不启用自动装配

更改自动装配为按照类型
比如bookServcice依赖BookDao–我们不需要描述其关系 程序会自动根据名字找到对应类的bean
1 | |
8.集合注入
1.数组

2.list

3.Set
1 | |
4.Map

5.Properties

9.案例分析-bean注入
我们要拿到druid的连接
1.配置bean -注入参数

我们就可以进行拿取
Set注入–进行注入传普通参数
10.加载properties文件
.properties 文件的结构和格式
- 文件扩展名:
.properties - 基本格式:每行包含一个键值对,格式为
key=value

加载模式

11.容器
创建过程包括多个关键步骤,从加载配置文件、解析 Bean 定义,到创建和初始化 Bean,再到处理 Bean 的生命周期和容器的启动与关闭。
1.初始化容器
加载配置:Spring 容器从配置文件或注解中加载应用程序的配置。这些配置文件可以是 XML 文件、Java 配置类(使用 @Configuration 注解)、或通过其他方式如 YAML 文件等

创建 ApplicationContext 实例
ApplicationContext context = new ClassPathXmlApplicationContext(“applicationContext.xml”);
2.加载 Bean 定义
流程
解析配置:Spring 容器解析配置文件中的 Bean 定义(包括 Bean 的类名、构造器参数、属性值等),或扫描标注有 @Component、@Service、@Repository、@Controller 等注解的类。
注册 Bean 定义:将解析得到的 Bean 定义注册到容器中。这包括 Bean 的名称、类型、作用域(如单例或原型)、依赖关系等信息。
创建 Bean 实例:根据 Bean 定义,Spring 容器创建 Bean 实例。Spring 使用反射机制调用 Bean 的构造函数(若是构造器注入)或默认构造函数。
依赖注入:在 Bean 实例创建后,Spring 容器根据 Bean 定义的依赖关系注入所需的依赖。这包括构造器注入、Setter 注入、字段注入等方式。
执行初始化方法:

处理 Bean 的生命周期
Bean 销毁:在容器关闭时,Spring 会销毁 Bean。->bean生命周期方法
容器的启动和关闭
启动容器:Spring 容器在创建完成后会启动并准备好处理应用程序的请求和交互。此时,所有的 Bean 都已经被创建和初始化完毕,可以使用它们提供的功能。
关闭容器:容器可以通过调用 ApplicationContext 的 close 方法来关闭。在关闭过程中,容器会执行 Bean 的销毁操作,释放资源,完成容器的清理工作。
3.容器接口分析

4.BeanFactory初始化

IOC DI Bean总结


高级篇
12.注解
1.@声明为Bean
将一个类声明为Bean

为了适配MVC->故此还有 @Controller @Service @Repository
2.纯注解配置


3.依赖注入


简单类型注入

4.加载properties文件


5.第三方bean管理例子
1.注册为bean

2.加入管理-导入式

扫描式

简单依赖注入

—连接池配置

XML与注解 配置区别

13.aop
1.Aop基础
1.原理
AOP的原理主要是通过使用代理对象来实现,在Spring中,AOP通过代理对象包装目标对象(被代理的对象),在代理对象中插入切面(aspect),实现对目标对象方法的增强。Spring AOP主要采用动态代理技术来实现AOP,其中包括JDK动态代理和CGLIB动态代理两种方式。
只有那些被 Spring 容器管理的 Bean(例如使用
@Component,@Service,@Repository, 或@Controller等注解的类,或者通过 XML 配置的 Bean),Spring 才能为它们创建代理对象。
代理对象的工作原理
代理对象的生成:
- 当容器启动并扫描到
@EnableAspectJAutoProxy注解时,Spring AOP 框架会自动创建一个代理对象来包装原始的UserServiceImpl对象。 - 根据
UserService接口类型,Spring 将使用 JDK 动态代理 创建代理对象。
- 当容器启动并扫描到
切面拦截方法:
- 代理对象接收到方法调用时,它会拦截调用并根据 AOP 配置执行相应的切面逻辑。
- 在这个例子中,代理对象会在方法执行前和执行后调用
LoggingAspect中的切面方法logBeforeMethod()和logAfterMethod()。
方法调用的委托:
在执行完切面方法后,代理对象会将方法调用委托给实际的目标对象 (
UserServiceImpl) 以完成核心业务逻辑41
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@Configuration
@EnableAspectJAutoProxy
public class AppConfig {
@Bean
public UserService userService() {
return new UserServiceImpl();
}
@Bean
public LoggingAspect loggingAspect() {
return new LoggingAspect();
}
}
---------------------------------
@Aspect
public class LoggingAspect {
@Pointcut("execution(* com.example.service.UserService.*(..))")
public void allUserServiceMethods() {}
@Before("allUserServiceMethods()")
public void logBeforeMethod() {
System.out.println("LoggingAspect: Before method execution");
}
@After("allUserServiceMethods()")
public void logAfterMethod() {
System.out.println("LoggingAspect: After method execution");
}
}
再框架中添加了个拦截器->依据正则过滤
2.场景
- 日志记录:记录方法的调用、参数、返回值等信息。
- 事务管理:管理事务的开始、提交、回滚等操作。
- 安全性:实现权限控制、加密解密等安全相关功能。
- 性能监控:统计方法的执行时间、次数等性能指标。
3.连接点 切面 切入点 通知
切面 @Aspect
定义一个类为切面类 -通知和切入点
@Aspect注解标识一个类为切面类,Spring会在扫描到这个注解的类时,自动创建代理对象,并将切面逻辑织入到目标方法中。
通知
通知(Advice)是指切面(Aspect)中定义的在程序执行过程中插入的代码片段,它们是在指定的连接点(Join Point)处执行的行为逻辑。通知的主要作用是定义在目标方法执行前后、异常抛出时等特定情况下,应该执行的动作或逻辑。
@Before和@After
1 | |
切入点
它用于定义通知(Advice)应用的具体位置(方法或类)。切入点决定了通知在哪些连接点(Join Point)上执行。切入点的主要作用是定义通知的应用范围,即通知应该在什么情况下、对哪些方法或类生效。
1 | |
-通知+切入点-哪个方法被aop进行管理-再什么时候运行
连接点
连接点是代码执行过程中的具体位置,可以被切面(Aspect)拦截并注入相应的增强逻辑。
当切入点表达式匹配到一个被 AOP 管理的类的方法时,这些方法就被认为是 连接点(Join Points)。
@Before(“execution(* Calculator.add(..))”)
通知+切入点
代表了 Calculator类的add方法上执行增强操作
案例代码
1 | |
1 | |
1 | |
2.Aop进阶
1.通知类型
前置通知(Before Advice):在目标方法执行之前调用通知方法。
对应注解:
@Before后置通知(After Returning Advice):在目标方法成功执行之后调用通知方法。
对应注解:
@AfterReturning后置异常通知(After Throwing Advice):在目标方法抛出异常后调用通知方法。
1
@AfterThrowing后置通知(After (finally) Advice):无论目标方法是否成功执行,都会调用通知方法。
1
@After环绕通知(Around Advice):在目标方法之前和之后执行通知方法,可以控制目标方法的执行过程。
对应注解:
@Around引入通知(Introduction Advice):向现有的对象添加新的方法或属性。
织入通知(AspectJ Advice):在AOP中指定切点和通知的组合。
案例
前置通知(Before Advice):在用户进行结账操作时,检查用户的权限,确保用户具有足够的权限进行结账操作。
后置通知(After Returning Advice):在用户提交订单成功后,记录订单信息到日志中,或者发送确认邮件给用户。
后置异常通知(After Throwing Advice):如果订单处理过程中出现异常,比如库存不足,就发送通知给相关人员进行处理。
后置最终通知(After (finally) Advice):无论订单处理成功与否,都需要关闭数据库连接或释放其他资源。
环绕通知(Around Advice):在处理订单之前和之后记录订单处理时间,以及性能监控等功能。
引入通知(Introduction Advice):向订单类引入一个新的接口,比如可追踪变更历史的接口。
织入通知(AspectJ Advice):定义一个切面,将上述的各种通知类型织入到订单处理的流程中。
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.ProceedingJoinPoint;
@Aspect
public class LoggingAspect {
@Before("execution(* com.example.service.OrderService.processOrder(..))")
public void beforeProcessOrder() {
System.out.println("Before processing order...");
}
@AfterReturning(pointcut = "execution(* com.example.service.OrderService.processOrder(..))", returning = "result")
public void afterProcessOrder(Object result) {
System.out.println("After processing order. Result: " + result);
}
@AfterThrowing(pointcut = "execution(* com.example.service.OrderService.processOrder(..))", throwing = "exception")
public void afterThrowingProcessOrder(Exception exception) {
System.out.println("Exception thrown during order processing: " + exception.getMessage());
}
@After("execution(* com.example.service.OrderService.processOrder(..))")
public void afterProcessOrderCompletion() {
System.out.println("After processing order completion...");
}
@Around("execution(* com.example.service.OrderService.processOrder(..))")
public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
long startTime = System.currentTimeMillis();
Object result = joinPoint.proceed();
long endTime = System.currentTimeMillis();
System.out.println("Order processing time: " + (endTime - startTime) + " milliseconds");
return result;
}
2.通知顺序
当多个切面匹配到同一个类时,可以按照切入点所在类的字母顺序来决定通知方法的执行顺序
1.类字母
按照匹配到的切入点的类字母决定先后顺讯
1.前置-字母排名靠前的先执行
2.后置-字母排名靠前的后执行
2.@Order
可以使用@Order注解来控制多个通知方法的执行顺序。通过@Order注解可以指定通知方法的执行顺序,数值越小的通知方法优先执行。
具体步骤如下:
- 在定义通知方法的类上添加
@Component或其他相关注解,使其成为Spring容器中的Bean。 - 在通知方法上添加
@Order注解,并指定执行顺序的数值,数值越小优先级越高。
1 | |
目标前-数字小的先执行
目标后-数字小的后执行
3.切入点
1.execution



2.注解aop开发
代码案例
首先,定义一个自定义注解CustomAnnotation:
1 | |
接着,在一个服务类中使用CustomAnnotation注解:
1 | |
在@CustomAnnotation("Custom Annotation Example")这个注解中,双引号里面的参数是注解的属性值。在定义自定义注解时,可以为注解定义属性,并在使用注解时为这些属性赋值。
在这个示例中,自定义注解CustomAnnotation定义了一个名为value的属性,因此在使用这个注解时,需要为value属性赋值。双引号中的内容 "Custom Annotation Example" 就是为value属性赋的具体数值。
当在切面类中通过反射获取带有CustomAnnotation注解的方法时,可以通过访问注解的属性值来获取这里传入的参数值,从而实现根据不同的属性值执行不同的逻辑处理。
然后,在切面类中使用@annotation注解匹配带有CustomAnnotation注解的方法:
1 | |
这个切入点表达式 @annotation(customAnnotation) 的作用是匹配所有被 @CustomAnnotation 注解标记的方法。
@annotation(customAnnotation) 是 AspectJ 提供的一个语法,用来匹配方法级别的注解。这里,customAnnotation 是一个参数,它表示目标方法上使用的 @CustomAnnotation。
同时annotatedMethod f方法的主要用处是可以在通知(Advice)方法中使用一个更清晰、易读的命名标识来引用切入点。
@Before("annotatedMethod(customAnnotation)") 表示在所有匹配 @annotation(customAnnotation) 切入点的方法执行之前,执行 beforeAnnotatedMethod 这个方法。
beforeAnnotatedMethod 方法将会在任何被 @CustomAnnotation 标记的方法执行之前运行。它可以访问这个自定义注解实例 customAnnotation,并获取该注解中的属性(例如 value() 方法)。
4.连接点


14.事务
0.事务的声明式管理
Spring 事务管理 依赖于 AOP 的思想和机制 来实现声明式事务管理。
在 Spring 中,当你使用 @Transactional 注解声明一个方法或类需要事务管理时,Spring AOP 会在运行时为这些方法或类创建一个代理对象(Proxy)。代理对象负责在方法调用之前开始事务,在方法调用之后提交或回滚事务。
Spring 使用 AOP 机制来织入事务管理代码。@Transactional 注解背后是通过 AOP 来实现的。在方法执行的前后,AOP 拦截器会自动进行事务管理操作(如事务开启、提交和回滚),而这些操作对业务代码是透明的。
这种方式被称为 声明式事务管理,它使用 @Transactional 注解指定哪些方法或类需要事务支持,不需要在业务代码中显式地编写事务处理逻辑。
切面
Spring 框架定义了一个 事务切面(Transaction Aspect),用来拦截被 @Transactional 标记的方法。这个切面是在方法调用前后执行相应的事务操作。
切入点
@Transactional
通知
通知逻辑
在方法执行前,事务切面拦截器会开启一个事务。
如果方法正常执行完成,则事务切面拦截器会提交事务。
如果方法执行过程中抛出了异常,事务切面拦截器会根据配置决定是回滚事务还是提交事务。
1.事务入门 -例子
假设我们有一个简单的用户管理系统,其中包括一个服务类 UserService,负责创建用户。我们希望在执行用户
1 | |
2.事务管理员 事务协调员
例子事务


3.事务配置


4.事务加入-规则

例子


如图-都加入同一事务-一旦有异常-日志也会回滚


解决

事务传播行为

0.1 Spring 整合mybatis

->将该注册为Bean


如图–以上配置全部进行修改



收纳


0.2 Spring整合测试
设定类运行器
整合spring运行器
