Spring相关知识点
Spring知识点
- Spring框架
-
依赖注入,控制反转的介绍
- 控制反转指的是一个过程,将原本对象自己控制的依赖关系变成外部容器来进行控制。
- 依赖注入是它的实现方式,Spring容器通过构造函数或者setter方法将依赖关系注入到对象中
-
Bean的注入方式
- 引导加载方式:通过Xml文件或者Java注解(@Bean注解)来实现
- 自动配置:即
①自动装配(声明setter方法,@Autowired 根据类进行匹配,多个则根据名字匹配(设置**@Qualifier注解可以指定Bean的名称)(设置required参数可以让其在找不到时不报错**),@Resouce JDK提供的 查找方式反一下)(在Bean上使用**@Primary注解可以设置多个匹配时的主类**。)
②组件扫描(@ComponentScan注解 默认会在当前包路径下扫描) - 自动装配的过程:再创建上下文时进行注册Bean定义,在Bean的实例化时进行解析(根据注解类型来选择执行Bean的后置处理器进行解析)
-
Spring IoC容器加载的流程
- 注册容器时,会先注册启动配置类,然后调用refresh()方法启动容器
- 准备初始化,对其设置启动日期和状态标志以及初始化监听器容器等
- 初始化Bean工厂,加载Bean定义,为其设置类加载器,添加后置处理器,注册系统环境等必要组件
- postProcessBeanFactory()留给子类的钩子方法,用来对工厂后处理,然后实例化并调用所有的工厂后置处理器。
- 为什么先加载工厂后置处理器:因为Bean定义在IoC容器加载时会先进行注册,而工厂后置处理器要对加载完的Bean定义进行扩展用的,所以要先加载。(比如解析配置类的Bean工厂后置处理器)
- 国际化消息的相关支持方法(默认的消息器会将消息传给父类(如果有的话),本身无实际作用)
- 初始化Spring容器的事件广播器(以支持事件监听)(如果用户未定义自己的广播器,则会创建一个默认的)。
- onRefresh()留给子类的钩子方法,用以注册特殊的Bean等(如Spring Boot在此注册Servlet容器)
- 注册事件监听器,将它们加入到刚才的事件广播器中。
- 实例化Bean。
- 创建容器完成,发布最终事件。
-
容器加载过程的扩展点:postProcessBeanFactory方法,onRefresh()方法
-
Spring启动过程相关的扩展点:
- 钩子方法
- Bean工厂加载过程:Bean工厂后置处理器,Bean定义后置处理器,环境后置处理器
- ImportSelector接口返回一个类全限定名称的数组集合,Spring会根据这个数组解析Bean定义
- ImportBeanDefinitionRegistrar接口,提供Bean定义的注册器,由用户将Bean定义传入
- Bean的加载过程:
① Aware接口(设置Bean名字,类加载器,Bean工厂的方法)。
② Bean的后置处理器(Bean初始化的前后进行调用)。
③ InitializingBean接口,在Bean初始化后调用。
④ @PostConstruct注解,在Bean初始化后调用。
⑤ 使用init-method声明了初始化方法,在Bean初始化后调用。
⑥ DisposableBean接口,在Bean销毁后调用。
⑦ @PreDestroy,在Bean销毁后调用。
⑧ 使用destory-method 声明销毁方法,在Bean销毁后调用。
⑨ FactoryBean接口:自定义Bean的创建逻辑。 - 监听器扩展,监听Spring中发布的相关事件
- ApplicationRunner / CommandLineRunner接口,在上下文刷新后提供扩展点(Spring Boot)
-
Bean的加载过程
- 先判断Bean是否为单例模式或者实现了SmartFactoryBean接口(FactoryBean的扩展接口)
- 判断成功,会去一二级缓存中找,找到则返回,如果三级缓存中有值,则调用缓存中的工厂方法创建Bean返回,如果都没有,则继续执行。
- 执行Bean实例化后将Bean包装成一个工厂加入三级缓存
- 根据Bean定义反射调用setter方法进行属性注入(此时会实例化别的Bean)
- 如果又再次回到开头,则会调用三级缓存的工厂方法,返回实例化的对象
- 相关属性注入完成,再次去一二缓存中找(没有三),防止重复创建动态代理
- 如果没有,则开始进行初始化流程,调用相关扩展接口加入到一级缓存
-
三级缓存的作用
一级缓存:保存创建好的Bean
二级缓存:存储已经实例化但尚未完成初始化的Bean
三级缓存:存储的是早期的对象工厂- 二级缓存行不行?
Spring中的三级缓存是为了AOP服务的,如果实现AOP则从三级缓存中拿到的实例化对象是AOP代理对象,如果使用二级缓存,则需要在注入属性时直接注入代理类,这不符合Bean的生命周期,Bean的AOP创建应在初始化后调用AOP的后置处理器创建代理。 - 多例Bean无法进行循环依赖:依赖循环没有出口,因为每次都会创建实例。
- 构造函数无法进行循环依赖(Spring无法直接解决):
构造器注入,会在通过构造函数实例化时就直接注入属性
此时可以加上**@Lazy注解**,让其注入时返回一个空对象,跳出依赖循环即可。 - Bean的并发创建:双重检查锁
在第一次查找缓存时,会对二三级缓存上锁(一级缓存不上锁,是为了减少性能影响),等线程创建完成对象加入一级缓存后,锁会被释放,同时唤醒后的线程因为找不到缓存(一级缓存已经找过了),则执行后面的逻辑,在依赖注入完成后,会再次上锁查找缓存(名字的由来),避免重复创建。
- 二级缓存行不行?
-
加载第三方的Bean:
- @Bean的方式来配置第三方类
@Import直接导入类的方式
- @Bean的方式来配置第三方类
-
FactoryBean的作用以及原理
- 它是一个接口,其中的getObject方法就是用来获取其产生的对象(且是懒加载的)
-
Spring相关的重要注解
- 常见注解的功能
-
Spring AOP(运行时增强)(常见的还有AspectJ AOP (编译时增强))
- 实现方式:JDK(针对接口的实现类)和CGLib(生成子类去重写)
在配置类中通过注解开启AOP支持(可以在此处设置在线程中暴露代理对象参数,这样就可以通过AOP的上下文拿到当前增强的对象,防止出现本类方法互相调用时AOP失效问题。) - 具体使用
①基于接口的配置。
②@AspectJ注解配置。
③AspectJ直接实现。 - 实现原理:基于动态代理,代理类会封装目标类,并拦截被通知的方法的调用,执行切面逻辑,再将调用转发给目标类。采用责任链的设计模式。
当配置类设置AOP启动参数,会注入一个AOP的Bean后置处理器,在初始化前会解析切面注解并缓存,初始化后会拿到之前的缓存,判断是否被切点命中,创建代理。 - 失效的原因:
–类内部调用方法失效(设置线程暴露参数,或者直接注入本类,然后调用)
–方法是private或者static(无法继承,实际上除了public都不行)
–目标类没有配置为Bean
- 实现方式:JDK(针对接口的实现类)和CGLib(生成子类去重写)
-
事务
- 四大特性:
原子性:所有操作要么全部成功,要么全部回滚
一致性:事务执行前和执行后必须处于一致性状态
隔离性:并发访问数据时,多个事务互相不干扰
持久性:事务一旦提交,对数据库的更改就是永久的 - 实现方式(编程式事务管理(编程的方式,灵活但难维护)和声明式事务管理(注解或xml配置,清晰方便))
- 传播行为
事务的传播行为指的是当一个事务方法调用另一个事务方法时,这个事务应该如何运行。
通过设置注解中的propagation参数,常见有三种:
默认的:无事务调用时会开启新事务,有事务调用时会融合外部事务(适合增删改)
SUPPORTS:无事务调用不开启事务,有事务调用时会融合外部事务(适合查询)
REQUIRES_NEW:无事务调用和有事务调用都会开启新事务(日志等) - 隔离级别
依赖数据库的事务隔离级别,通过注解中的isolation参数设置()
脏读(RC)
不可重复读(RR)
幻影读(SERIALIZABLE)
- 传播行为
- 实现原理(针对声明式事务管理)
基于AOP实现的(要在配置类中通过注解开启事务注解支持)
会为此类创建一个代理,调用会加上try-catch语句块
Spring事务信息存放在ThreadLocal中,所以一个线程只能有一个事务- try:
- 判断ThreadLocal是否有数据库连接,如果有,说明现在是内嵌事务,执行下面语句:
- 如果是融入行为:不会重新创建新事务,将新事务的标志字段改为false
- 如果是创建行为:会将事务状态信息暂存后清空,重写创建一个事务
- 否则正常创建数据库连接,并且修改自动提交为false,执行目标方法
- catch:出现异常,需要回滚就会回滚,否则正常提交
- 无异常执行完成,当新事务标志字段为true则提交事务,否则恢复被清理的旧事务。
- 四大特性:
-
事件监听机制(观察者设计模式)
- 实现原理:底层通过事件广播器来发布事件,可以自定义事件监听器,Spring容器会帮我们自动加入进去。
-
Spring Boot
- Spring Boot框架
- 与Spring的主要区别
- 两者关系:Spring Boot不像Spring,不是一个框架,它是一个可以快速构建Spring脚手架工具,为其开发提供便利
- 核心注解:
@SpringBootApplication(其为复合注解,还包括**@EnableAutoConfiguration @SpringBootConfiguration**) - 内嵌Servlet容器
- Spring Boot的启动流程
- 运行main方法,初始化SpringApplication(发布事件)
- 运行run方法,内部会读取环境变量,打印Banner,设置一些参数等(发布事件)
- 创建SpringApplication上下文与初始化上下文,将启动类作为配置类注册
- 调用refresh方法加载IoC容器(发布事件)
- 解析**@Import加载的所有自动配置类**
(自动配置类:目的就是为我们做第三方库的自动配置) - onRefresh方法中会创建servlet容器
- 解析**@Import加载的所有自动配置类**
- 执行扩展接口(ApplicationRunner和CommandLineRunner接口)(发布事件)
- 执行异常也会发布事件
- 大量利用监听器进行扩展(监听事件的发布)
- 自动配置加载的原理:
- 通过**@SpringBootConfiguration映入了@EnableAutoConfiguration**注解
- 其中使用**@Import导入了一个deferredImportSelcetor**
- 加载IoC容器时会解析@Import注解
- 会读取所有jar包META-INF/spring.factories文件(SPI),过滤出所有AutoConfigurationClass类型的类
- 通过**@Condition排除无效的自动配置类**
- 内嵌Servlet容器启动原理(默认Tomcat)
- 当引用了web的场景启动器,就会导入容器启动的自动配置类,会导入一个Web容器工厂,在OnRefresh方法创建容器
- Jar包能直接运行的原因
- Spring Boot提供了一个maven插件,此时打包会将依赖的jar包和Spring Boot相关的类一起打包。
同时启动时会分别加载依赖的jar包和启动Main函数。
- Spring Boot提供了一个maven插件,此时打包会将依赖的jar包和Spring Boot相关的类一起打包。
- Servlet相关概念
- 三大组件:
Servlet:处理客户端请求的核心组件
Listener:用于监听 Web 应用程序中各种事件的组件
Filter:用于在请求到达 Servlet 之前或响应返回客户端之前对请求和响应进行处理的组件 - Spring Boot可以在配置类中的注册 注册器Bean,并在其中注册相关组件
- 三大组件:
- 日志框架和门面
- 日志实现的方式有非常多,为了统一各个日志框架与日志门面,出现了适配器(让不同日志门面统一实现SLF4J门面)和桥接器(让不同日志框架实现SLF4J门面),只需要加入不同的适配器和桥接器就可以实现日志的整合。
- Spring MVC测试方法
- MockMvc:
- 不需要启动Web应用,可以对http请求进行模拟,同时提供一套验证工具,在测试类注入MockMvc对象,测试类加上**@AutoConfigureMockMvc**即可使用。
- RestTemplate
- 主要适用微服务远程调用(本地也行),在普通类中的构造函数可以通过builder构造一个
测试类通过TestRestTemplate直接new一个。(使用完整的远程调用请求路径,以及需要使用无参构造函数)
- 主要适用微服务远程调用(本地也行),在普通类中的构造函数可以通过builder构造一个
- PostMan/ApiPost工具
- Swagger API测试文档
- MockMvc:
- 与Spring的主要区别
SSM
- SSM框架
- Spring MVC
- 工作流程:
- 客户端向服务器发送一个HTTP请求
- 前端控制器(DispatcherServlet)接收请求
- 根据请求的URL和其他信息,通过HandlerMapping确定请求应该由哪个**处理器(Controller)**来处理
- 确定处理器后,DispatcherServlet会通过HandlerAdapter来调用处理器。
- 处理器(Controller)具体的业务逻辑实现类,它接收请求参数,执行业务逻辑,并返回一个ModelAndView对象。
- 返回ModelAndView对象后,DispatcherServlet会通过**视图解析器(ViewResolver)**解析视图名称,去找到对应视图。
- 找到视图资源后,DispatcherServlet 会将模型数据传递给视图,并进行渲染。
- 最后,DispatcherServlet 将生成的响应内容发送回客户端,客户端(如浏览器)会显示响应内容。
- HandlerInterceptor:用于拦截处理请求,可以在请求处理前、处理中和处理后执行特定逻辑。
- ControllerAdvice:用于全局处理控制器的异常、数据绑定和数据校验。
- 工作流程:
- Spring 详细戳这
- Mybatis
- 三层架构
- 表示层
- 业务逻辑层
- 数据访问层
- Spring MVC
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 晨星的博客!
评论