Spring总结(IOC、AOP原理以及Spring事务)
1|0一、概述
1、Spring是一个开源免费且轻量级的框架 , 非侵入式的 .
2、控制反转 IoC , 面向切面 Aop
3 、对事物的支持 , 对框架的支持
一句话概括:
Spring 是一个轻量级的控制反转(IOC),面向切面(AOP)的框架
2|0二、Spring下载
Sprig官网:Spring.io 去到官网即可下载
GA:稳定通用版本、SNAPSHOT : 快照版本
Spring历史版本下载地址:https://repo.spring.io/ui/native/release/org/springframework/spring
Spring5 Runtime 结构示意图
Core 就是我们的Spring的核心 ,如下就是我们如果使用Spring必须导入的Jar包 ,commons-logging
必须但不属于Spring;
3|0三、IOC 控制反转
3|11、IOC底层原理
IOC就是通过 工厂模式 + 反射 + XML解析 实现
我们通常所说的IOC容器本质上就是一个对象工厂,而我们的Spring提供IOC容器实现的两种方式(也就是两个接口,如下)
1、BeanFactory : IOC容器的基本实现,是Spring内部使用的接口,不提供给开发人员使用 ;
- 加载配置文件的时候,不会创建对象,而是当我们的使用的时候才回去创建对象!
2、ApplicationContext : BeanFactory的子接口提供更多更强大的功能,一般由开发人员进行使用 ; 【推荐】
- 加载配置文件的时候,会把配置文件中的对象进行创建!
ApplicationContext接口的实现类
查看ApplicationContext接口的继承结构
区别:
- ClassPathXmlApplicaitonContext : 加载的是我们的src路径下的资源文件
- FileSyustemXmlApplicationContext: 加载的就是我们系统盘也就是电脑的绝对路径(全路径):如:D:// …
总结
我们通过Spring提供的两种接口 BeanFactory 和 ApplicationContext ,以及其具体的实现类通过读取我们的xml文件创建我们的对象工厂,也就是IOC容器!接下来我们的IOC容器通过反射的方式创建出对象!
3|22、IOC创建对象的方式
IOC有两种创建对象的方式: 方式一:无参构造 + set注入属性值 ,方式二:有参构造
1、无参构造(默认)
2、有参构造
3、DI依赖注入
DI : 依赖注入(Dependency Injection)也称属性注入 ;
方式一 :使用set方法进行注入 : 我们使用无参构造创建对象,这个类就会通过set方法注入属性,完成对象的创建!
方式二 :使用有参构造进行注入:我们使用有参构造创建的对象对通过构造方法赋值 !
扩展 :p命名和c命名注入
1、P命名空间注入 : 需要在头文件中加入约束文件
2、c 命名空间注入 : 需要在头文件中加入约束文件
其实p命名注入本质上就是我们的set注入,c命名注入本质上则是我们的构造器注入
3.1、注入空值和特殊符号
向我们的对象属性中注入空值
属性值中注入特殊符号
3|33、IOC中Bean的类型
IOC创建的Bean分为两种:FactoryBean(工厂Bean) 和 Bean(普通Bean)
FactoryBean 和 Bean的区别:
-
普通Bean:就是在配置文件中定义的什么类型,经过IOC容器创建后返回的就是什么类型
-
工厂Bean:则是IOC创建的类型可以不是xml中定义的类型
myBean实现FactoryBean
通过IOC获取这个MyBean,进行测试 :
3|44、Bean的作用域
在Spring里面,设置创建Bean实例是单实例(默认)还是多实例
通过标签中scop属性设置我们Bean的作用域,如下:
区别:
- singleton:单例模式,表示Spring的IOC容器当中只能存在一个Bean实例,默认的。
- prototype:多实例模式,表示每次从IOC容器当中取一个Bean实例的时候,都是一个新的Bean 。
- request:每次创建对象,都放在我们的Request域当中(很少用)。
- session:每次创建对象,都放在我们的session域当中(很少用)。
扩展
关于singleton和prototype还存在一个区别就是:
当我们的scop=singleton
的时候我们的对象是会在ApplicaitionContex加载xml文件的时候创建的;
当我们的scop=prototype
的时候我们的对象不是在加载xml的时候创建的,而是在调用getBean方法的时候创建的!
3|55、Bean的生命周期
也就是我们Bean对象从创建到销毁的过程
- 通过构造器创建bean实例(无参数构造)
- 为bean的属性设置值和其他bean引用(调用set方法)
- 调用bean的初始化方法(需要进行配置初始化方法)
- bean可以使用了(对象获取到了)
- 当容器关闭的时候,调用bean的销毁方法(需要进行配置销毁的方法)
演示bean的生命周期
1、编写一个Orders类,为其设置set方法,
2、编写xml文件
3、编写测试方法,对生命周期进行测试
4、查看测试结果
上述的五步就是我们Bean的生命周期,但是是不考虑后置处理器的情况下是五步,如果考虑的话是如下七步:
考虑后置处理器
- 通过构造器创建bean实例(无参数构造)
- 为bean的属性设置值和其他bean引用(调用set方法)
- 将我们bean实例传入我们的后置处理器方法:postProcessBeforeInitialization()
- 调用bean的初始化方法(需要进行配置初始化方法)
- 将我们bean实例传入我们的后置处理器方法:postProcessAfterInitialization()
- bean可以使用了(对象获取到了)当容器关闭的时候,
- 调用bean的销毁方法(需要进行配置销毁的方法)
让我们来创建后置处理器来实现我们的3、5步骤
我们只需创建一个后置处理器,然后将处理器注入到我们的IOC容器当中即可,我们的Spring会默认的将其加在IOC容器中的所有bean!
1、创建后置处理器:创建一个类实现BeanPostProcessor接口,并重写两个方法
2、注入到我们的IOC容器
测试添加后置处理器的执行结果
可以看到我们的Bean的生命周期就变为七步了!
3|66、自动装配
我们上边说的是如何将对象注入到IOC容器当中,自动装配简单来说就是自动的从IOC容器中去取对象!
- 自动装配是使用spring满足bean依赖的一种方法
- spring会在应用上下文中为某个bean寻找其依赖的bean。
Spring的自动装配需要从两个角度来实现,或者说是两个操作:
- 组件扫描(component scanning):spring会自动发现应用上下文中所创建的bean;
- 自动装配(autowiring):spring自动满足bean之间的依赖,也就是我们说的IOC/DI;
组件扫描和自动装配组合发挥巨大威力,使得显示的配置降低到最少。
推荐不使用xml配置开启自动装配, 而是使用注解,无论是xml还是注解开启自动装配,都需要先了解一下自动装配的类型:byName 和 byType 这两类,自动装配的类型就是我们从IOC容器中按照什么找到我们所需的bean
6.1、自动装配的类型
自动装配的类型分为两种:byName 和 byType 这两类
- byName:需要保证所有bean的id是唯一的,并且这个bean需要和自动注入的属性的set方法的名字一致
- byType:需要保证所有bean的class是唯一的,并且这个bean需要和自动注入的属性的类型一致
知道了自动装配类型的区别,那么就可以学习开启自动装配的两种方式了,如下 :
6.2、自动装配的方式
开启自动装配的方式有,xml配置 和 注解 两种方式!
前提:需要自动装配的属性必须是引用数据类型!
1、XML配置开启自动装配
2、注解开启自动装配
注解开启有如下常用注解,将如下主注解放在需要自动装配的属性上即可!
-
@Autowired : 默认是按照类型(ByType)自动装配,如果出现相同类型,可以通过搭配**@Qualifire**指定bean的名称,实现ByName自动装配,@Autowired是Spring的注解!
-
@Resource:默认是按照名字(ByName)自动装配的,@Resource有两个重要的属性:name和type,而Spring将@Resource注解的name属性的值解析为bean的名字,而type属性的值则解析为bean的类型。所以,如果使用name属性,则使用byName的自动注入策略,而使用type属性时则使用byType自动注入策略。如果既不制定name也不制定type属性,这时将通过反射机制使用byName自动注入策略。而@Resource是我们Java的原生注解!
自动装配就这么简单!
扩展一下
@Autowired(required=false) 说明:false,对象可以为null;true,对象必须存对象,不能为null。
3|77、注解实现DI和对象的创建
前面我们一直通过在xml标签的形式创建对象,接下来我们介绍一下注解的方式创建对象!
1、注解实现对象的创建
Spring提供如下四种注解来实现对象的创建
- @Component
- @Controller:
- @Service:
- @Repository:
以上四个注解的作用是一样的,都可以用来创建bean,这样分只是为了更好的进行分层。
使用注解的具体步骤:
1、引入AOP的依赖(我们如果使用Maven导入webmvc会自动导入aop)
2、开启组件扫描(注解扫描,为有注解的类创建对象)
2.1、引入context名称空间:
2.2、配置扫描哪些包下的注解
3、在指定包下编写类,增加注解
4、测试
5、开启组件扫描的细节
这一块内容知道就好,通过两个例子演示
- 样例一:
- 样例二:
2、注解实现DI(属性注入)
引用数据类型的属性,通过@Atowired、@Quilifire、@Resource 实现,而基本数据类如何实现DI呢?
@Value :注入普通类型属性
- 一个样例即可学会:
小结一下
XML与注解比较
- XML可以适用任何场景 ,结构清晰,维护方便
- 注解不是自己提供的类使用不了,开发简单方便
xml与注解整合开发 :推荐最佳实践
- xml管理Bean
- 注解完成属性注入
- 使用过程中, 可以不用扫描,扫描是为了类上的注解
作用:
- 进行注解驱动注册,从而使注解生效
- 用于激活那些已经在spring容器里注册过的bean上面的注解,也就是显示的向Spring注册
- 如果不扫描包,就需要手动配置bean
- 如果不加注解驱动,则注入的值为null!
3|88、通过JavaConfig创建对象
基于Java类进行配置
JavaConfig 原来是 Spring 的一个子项目,它通过 Java 类的方式提供 Bean 的定义信息,在 Spring4 的版本, JavaConfig 已正式成为 Spring4 的核心功能 。
1、编写一个实体类,Dog
2、新建一个config配置包,编写一个MyConfig配置类
3、测试
关于这种Java类的配置方式,我们在之后的SpringBoot 和 SpringCloud中还会大量看到,我们需要知道这些注解的作用即可!
4|0四、AOP 面向切面
面向切面编程(方面),利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分耦合度降低,提高开发效率!
通俗描述:在不修改源代码的方式,在主干功能当中添加新功能!
4|11、AOP底层原理
AOP的底层就是动态代理,而其动态代理也根据情况的不同分为JDK动态代理和CGLIB动态代理
4|22、JDK动态代理的实现
JDK动态代理是在有接口的情况下使用,所以我们需要先创建接口实现类的代理对象,这一步通过Proxy的方法可以实现!
Proxy : java.lang.reflect.Proxy
方法有三个参数:
1、类加载器
2、增强方法所在的类,这个类的接口 ,支持多个接口
3、实现这个接口InvocationHandler ,创建代理对象,写增强方法
具体的实现步骤
1、编写一个接口,UserDao
2、创建接口的实现类,UserDaoImpl
3、通过Proxy创建代理类,实现方法增强
4、测试结果,实现方法增强!
4|33、AOP术语
介绍一下AOP当中的的相关术语,例如:发动机术语是引擎
1、连接点 :类里面的哪些方法可以被增强,这些方法称为连接点 ;
2、切入点:实际被真正增强的方法,称为切入点 ;
3、通知(增强):实际增强的逻辑部分就称为通知 ;通知也分5种:前置通知 、后置通知 、环绕通知、异常通知、最终通知!
4、切面 :是一个动作,指的是将通知应用到切入点的过程!
4|44、AOP操作(AspectJ)
Spring框架一般都是基于Aspectj实现AOP操作!
1、什么是AspectJ ?
- AspectJ不是Spring的组成部分,独立AOP框架,一般把AspectJ和Spring框架一起使用,进行AOP操作!
2、基于Aspectj实现AOP操作的方式 :
- 基于xml配置文件实现
- 基于注解的方式实现(推荐)
4.1、实现AOP操作的准备
如下开始使用Spring 和 AjpectJ 来实现AOP的操作!
1、环境准备:Ajpectj + Spring
2、切入点表达式
- 切入点表达式的作用:知道对哪个类里面的哪个方法进行增强
- 语法结构:
例1:对com.sqx.dao.BookDao
类里面的add方法进行增强
例2:对com.sqx.dao.BookDao
类里面的所有方法进行增强
例3:对com.sqx.dao
包里面的所有类,类里面的所有方法进行增强
4.2、AOP操作(AspectJ注解)
通过AspectJ注解的方式实现AOP操作
1、创建一个类,在类中定义方法
2、创建增强类(编写增强逻辑)
3、进行通知的配置
3.1、在Spring配置文件,开启注解扫描
3.2、使用注解创建User和ProxyUser:也就是在类的上边加上@Component
3.3、在增强类上添加一个注解 @AspectJ
3.4、在Spring配置中开启生成代理对象:同时需要引入aop的命名空间
3.5、配置不同类型的通知
1、在增强类的里面,在作为通知方法上面添加通知类型注解,使用切点表达式配置
2、进行测试
方法增强成功!
4、剩余的配置细节
对以上通知类型都进行测试,我么看一下有什么问题?
①、我们发现,我们为一个切点多次增强,切入点表达式出现冗余,因此,我们可以将切点表达式抽取出来,生成一个公共切入点
1、定义公共切入点:
2、使用公共切入点:
以上就解决了我们的切入点冗余的问题!
②、如果出现如下情况:多个增强类对同一个方法进行增强,我们需要制定其优先级
我们通过@Order注解来设置增强类优先级:这个值越小优先级越高!
执行测试,查看结果
4.3、AOP操作(AspectJ配置文件)
通过xml配置文件的方式实现AOP操作(很少使用,了解即可!)
5|0五、Spring事务
事务一般添加到JavaEE三层结构里面的Service层(业务逻辑层)
Spring事务管理的两种方式:1、编程式事务管理 2、声明式事务管理(推荐)
区别:编程式事务管理,是我们通过代码保证我们的事务,显得比较臃肿,因此推荐声明式事务管理
5|11、编程式事务管理
如下是编程式事务的一个演示:
5|22、声明式事务管理
声明式事务的使用方式有如两种:
- 基于注解的方式【方便、简单、推荐】
- 基于xml配置文件方式
声明式事务的底层,使用的就是我们的AOP原理
Spring事务管理的一些API :
如果我们的Spring整合了Mybatis 、jdbcTemplate都是使用的DataSourceTransactionManger
这个事务管理器!
2.1、注解方式实现
1、配置Spring的事务管理器
2、在Spring配置文件,开启事务注解
3、在Service类上面(获取Service类里面的方法上面)添加事务注解
- @Transactional,这个注解可以加在类上边,也可以加在方法上面
- 如果把这个注解添加在类上面:这个类里面所有方法都添加事务
- 如果把这个注解添加在方法上面:为这个方法添加事务
到此,我们的声明式事务,通过注解的方式就已经开启了!
@Transactional扩展 : 了解一个这个注解的一些属性参数
常用的有如下:
-
propagation :事务的传播行为
指的是事务方法(对数据库表中数据发生改变的方法,统称事务方法),之间的相互调用!
事务的传播行为有七种:
参考文章:https://blog.csdn.net/weixin_39625809/article/details/80707695
-
isolation:事务隔离级别
- 在此处主要是指的多个开启事务的方法的并发问题,本质还是跟我们MySQL中的事务隔离级别一致!
-
timeout:超时时间
- 事务需要在一定时间内进行提交,如果说在这一段时间内不提交,就会发生回滚!
- 默认值是-1 , 设置时间以秒为单位
-
readOnly:是否只读
- 读:查询操作,写:增删改操作’
- 默认值为false , 表示当前事务当中可以查询可以查询和增删改操作
- 设置为true , 当前事务中只支持读操作
-
rollbackFor:回滚
- 设置出现哪些异常,执行回滚
-
noRollbackFor:不回滚
- 设置出现哪些异常,不执行回滚
2.2、xml配置文件方式实现
实际开发,我们依然是用注解,但是xml配置方式仍需了解一下!
前提:声明式事务本质还是aop实现的,我们注解只是代替了我们手动切入事务的这个步骤,xml则需要我们手动的完成这个步骤!
1、依然是配置我们事务管理器
2、配置我们的通知
3、配置切入点和切面
xml配置文件方式实现声明式事务完成!
2.3、完全注解实现
通过JavaConfig的方式配置我们所有信息,无需要xml文件
需要注意:
事务相关就到此完结!
6|0六、Spring整合日志框架
Spring5 框架自带了通用的日志封装,而且也能整合其他日志工具 如 : Log4j 、Log4j2
由于Spring5 移除了Log4j CofigerListener(使用Log4j的核心),如果需要Log4j 要将Spinrg5降为4版本,所以官方建议使用Log4j2
参考文章:https://blog.csdn.net/zjh2016/article/details/103170578
6|11、整合Log4j2日志
1、引入相关依赖
需要导入如下的4个依赖,才能使用Log4j2
2、创建Log4j2.xml配置文件
配置都是如下:
到这里我们Log4j2就已经开启了,但是如果我们呢想要手动使用Log4j2呢?
3、进行如图操作就好了
就如下两步即可!
完结!
7|0七、Spring整合单元测试框架
常见的单元测试框架JUnit4 、JUnit5 我们的Spring5 都是支持的,我们逐个测试!
参考文章:https://blog.csdn.net/sinat_32336967/article/details/112275292
前提:先准备Spring5的环境
7|11、整合JUnit4测试
1、导入相关依赖
2、Spring5+Junit4单元测试
7|22、整合JUnit5测试
1、引入相关依赖
2、Spring5+Junit5单元测试代码
7|33、总结
不同点
1、使用注解不同
Spring5+Junit4时,使用如下两个注解:
- @RunWith(SpringJUnit4ClassRunner.class)
- @org.junit.Test
Spring5+Junit5时,使用如下两个注解:
- @ExtendWith(SpringExtension.class)
- @org.junit.jupiter.api.Test
2、整合时使用的启动类不同
- 整合Junit4时是:org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
- 整合Junit5时是:org.springframework.test.context.junit.jupiter.SpringExtension;
两者均是spring-test包中提供的类。
相同点
加载配置类或者配置文件均使用注解 :
@ContextConfiguration(classes = AppConfiguration.class) 或者 @ContextConfiguration(classpath = “beans.xml”)
注意事项:在使用Spring5时,Junit版本最低为4.12,否则就会报错。
__EOF__

本文链接:https://www.cnblogs.com/qxsong/p/15837230.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理