【面试专题】Spring篇②

📃个人主页个人主页

🔥系列专栏:Java面试专题

目录

1.spring-bean的循环依赖

2.springMVC执行流程

3.Springboot自动配置原理

4.Spring框架常见的注解(Spring,SpringMVC,SpringBoot)


1.spring-bean的循环依赖

循环依赖:循环依赖其实就是循环引用 , 也就是两个或两个以上的 bean 互相持
有对方 , 最终形成闭环。比如 A 依赖于 B,B 依赖于 A

循环依赖在 spring 中是允许存在, spring 框架依据三级缓存已经解决了大部
分的循环依赖
① 一级缓存:单例池,缓存已经经历了完整的生命周期,已经初始化完成的
bean 对象
② 二级缓存:缓存早期的 bean 对象(生命周期还没走完)
③ 三级缓存:缓存的是 ObjectFactory ,表示对象工厂,用来创建某个对象的

那具体解决流程清楚吗?

  • 第一,先实例A对象,同时会创建ObjectFactory对象存入三级缓存 singletonFactories
  • 第二,A在初始化的时候需要B对象,这个走B的创建的逻辑
  • 第三,B实例化完成,也会创建ObjectFactory对象存入三级缓存 singletonFactories
  • 第四,B需要注入A,通过三级缓存中获取ObjectFactory来生成一个A的对象,同时存入二级缓存,这个是有两种情况,一个是可能是A的普通对象,另外一个是A的代理对象,都可以让ObjectFactory来生产对应的对象,这也是三级缓存的关键
  • 第五,B通过从通过二级缓存earlySingletonObjects 获得到A的对象后可以正常注入,B创建成功,存入一级缓存singletonObjects
  • 第六,回到A对象初始化,因为B对象已经创建完成,则可以直接注入B,A创建成功存入一次缓存singletonObjects
  • 第七,二级缓存中的临时对象A清除

构造方法出现了循环依赖怎么解决?
由于 bean 的生命周期中构造函数是第一个执行的, spring 框架并不能解决构造函数的的依赖注入,可以使用@Lazy 懒加载,什么时候需要对象再进行 bean对象的创建。

2.springMVC执行流程


1 、用户发送出请求到前端控制器 DispatcherServlet ,这是一个调度中心
2 、 DispatcherServlet 收到请求调用 HandlerMapping (处理器映射器)。
3 、 HandlerMapping 找到具体的处理器 ( 可查找 xml 配置或注解配置 ) ,生成处理器对象及处理器拦截器( 如果有 ) ,再一起返回给 DispatcherServlet 。
4 、 DispatcherServlet 调用 HandlerAdapter (处理器适配器)。
5 、 HandlerAdapter 经过适配调用具体的处理器( Handler/Controller )。
6 、 Controller 执行完成返回 ModelAndView 对象。
7 、 HandlerAdapter 将 Controller 执行结果 ModelAndView 返回给DispatcherServlet。
8 、 DispatcherServlet 将 ModelAndView 传给 ViewReslover (视图解析器)。
9 、 ViewReslover 解析后返回具体 View (视图)。
10 、 DispatcherServlet 根据 View 进行渲染视图(即将模型数据填充至视图中)。
11 、 DispatcherServlet 响应用户。
当然现在的开发,基本都是前后端分离的开发的,并没有视图这些,一般都
是 handler 中使用 Response 直接结果返回

①用户发送请求到前端控制器DispatcherServlet

②DispatcherServlet收到请求调用HandlerMapping(处理器映射器)。

③HandlerMapping找到具体的处理器,生成处理器对象及处理器拦截器(如果有),再一起返回给DispatcherServlet。

④DispatcherServlet调用HandlerAdapter(处理器适配器)。

⑤HandlerAdapter经过适配调用具体的处理器(Handler/Controller)。

⑥方法上添加@ResponseBody

⑦通过HttpMessageConverter来返回结果转换为JSON并响应

3.Springboot自动配置原理

在 Spring Boot 项目中的引导类上有一个注解 @SpringBootApplication ,这个
注解是对三个注解进行了封装,分别是:
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan
其中 @EnableAutoConfiguration 是实现自动化配置的核心注解。 该注解通过 @Import 注解导入对应的配置选择器。关键的是内部就是读取了该项目和该项目引用的Jar 包的的 classpath 路径下 META- INF/spring.factories 文件中的所配置的类的全类名。
在这些配置类中所定义的 Bean 会根据条件注解所 指定的条件来决定 是否需要
将其导入到 Spring 容器中。
一般条件判断会有像 @ConditionalOnClass 这样的注解,判断是否有对应的class文件,如果有则加载该类,把这个配置类的所有的 Bean 放入 spring 容器中使用。

什么是自动装配

Spring Boot 相比于 Spring 的一个很大进步点在于不用再手动配置一系列配置文件,Spring Boot 提供了配置应用程序和框架所需要的基本配置,这就是自动配置。本节会先通过源码介绍自动装配,并在本节最后给出总结。

Spring Boot 启动器

Spring Boot 中的一系列启动器是自动装配的最佳实践。比如当引入了一个 spring-boot-starter-web 依赖:

java 复制代码
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
</dependency>

Spring Boot 框架就会自动引入 web 环境所有的依赖,并且自动配置,Spring Boot 将所有的功能场景,都变成一个个启动器,想要用什么功能,只需要找到对应的启动器就可以了。

Spring Boot 的所有启动器可以在官网 https://docs.spring.io/spring-boot/docs/current/reference/html/using-spring-boot.html#using-boot-starter中找到,下图是所有启动器中的一小部分:

自动装配原理分析

Spring Boot 的主程序也可以称为启动类,这是开启 Spring Boot 项目的入口。查看源代码推荐使用 IDEA。

java 复制代码
package com.lanqiaoyun.springbootdemo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringbootdemoApplication {

  public static void main(String[] args) {
    SpringApplication.run(SpringbootdemoApplication.class, args);
  }
}

@SpringBootApplication 注解标注这个类是一个 SpringBoot 的启动类,这个注解也是自动装配的核心。

@TargetRetentionDocumentedInherited 四个注解是标准的元注解,核心在于@SpringBootConfiguration@EnableAutoConfiguration这两个注解。

通过继续进入注解内部,可以将@SpringBootConfiguration@EnableAutoConfiguration这两个注解的结构表示出来:

  • @SpringBootConfiguration : Spring Boot 的配置
    • @Configuration : Spring 配置类
      • @Component : Spring 的组件
  • @EnableAutoConfiguration : 自动配置
    • @AutoConfigurationPackage : 自动配置包
      • @Import({Registrar.class}) : 自动配置包注册
      • @Import({AutoConfigurationImportSelector.class}) : 导入选择器

@SpringBootConfiguration 声明了这个类为 SpringBoot 的组件,@EnableAutoConfiguration 是自动配置的核心,其中@AutoConfigurationPackage 对配置包进行了注册,AutoConfigurationImportSelector 类来进行自动装配。

继续来看看 AutoConfigurationImportSelector 这个类。

  1. 引入环境。
  2. 引入 bean 加载器。
  3. 引入资源加载器。
  4. 配置导入。

继续向下看,selectImports 中 的getAutoConfigurationEntry 方法第 86 行代码将所有的配置通过 getCandidateConfigurations 方法放进一个 List 集合中。

继续进入 getCandidateConfigurations 方法,这个配置获取的路径是 EnableAutoConfiguration.class,也就是@SpringBootApplication 所依赖的两个重要注解的其中一个。这段代码最终想表达的意思是将启动类下的所有配置都导入。

进入 LoadFactoryNames 或者就从 Assert.notEmpty 的信息中,可以发现这些配置来自于 META-INF/spring.factories 中,从 jar 包中可以查看到具体的目录结构。

在 spring.factories 文件中存在大量 xxxAutoConfiguration,这个文件记录了所有 starter 的自动装配类,就是这些类在容器中导入了场景需要的所有组件;并通过 @Configuration 自动配置。

通过一张图来总结一下自动装配的原理,通过上面对源码的分析,可以看出 SpringBoot 所有的自动配置都在启动类中被扫描和加载。所有的自动配置类都在 spring.properties 中。

@ConditionalOnClass 这样的注解,判断是否有对应的class文件,如果有则加载该类,把这个配置类的所有的Bean放入spring容器中使用。

自动装配总结起来可以分为以下几步:

  1. Spring Boot 在启动的时候,从类路径下/META-INF/spring.factories 获取指定的值;
  2. 将这些自动配置的类导入容器,自动配置就会生效,进行自动配置!
  3. 以前我们需要自动配置的东西,现在 Spring Boot 帮我们做了
  4. 自动配置的东西都在 spring-boot-autoconfigure.jar 这个包下
  5. 它会把所有需要导入的组件,以类名的方式返回,这些组件就会被添加到容器;
  6. 容器中也会存在非常多的 xxxAutoConfiguration 的类(@Bean),就是这些类给容器中导入了这个场景需要的所有组件;并通过@Configuration 自动配置。
  7. 有了自动配置类,免去了我们手动编写配置文件的步骤。

4.Spring框架常见的注解(Spring,SpringMVC,SpringBoot)

Spring 的常见注解有哪些?
第一类是:声明 bean ,有 @Component 、 @Service 、 @Repository 、 @Controller
第二类是:依赖注入相关的,有 @Autowired 、 @Qualifier 、 @Resourse
第三类是:设置作用域 @Scope
第四类是: spring 配置相关的,比如 @Configuration , @ComponentScan 和 @Bean
第五类是:跟 aop 相关做增强的注解 @Aspect , @Before , @After ,@Around, @Pointcut
SpringMVC常见的注解有哪些?
@RequestMapping :用于映射请求路径;
@RequestBody :注解实现接收 http 请求的 json 数据,将 json 转换为 java 对象;
@RequestParam :指定请求参数的名称;
@PathViriable :从请求路径下中获取请求参数 (/user/{id}) ,传递给方法的形式参数;@ResponseBody :注解实现将 controller 方法返回对象转化为 json对象响应给客户端。@RequestHeader :获取指定的请求头数据,还有像@PostMapping、 @GetMapping 这些。
@RestController:@Controller+@ResponseBody
Springboot常见注解有哪些?
Spring Boot 的核心注解是 @SpringBootApplication , 他由几个注解组成 :
@SpringBootConfiguration : 组合了- @Configuration 注解,实现配置文件的功能;
@EnableAutoConfiguration :打开自动配置的功能,也可以关闭某个自动配置的选项
@ComponentScan : Spring 组件扫描

相关推荐
禁默36 分钟前
深入浅出:AWT的基本组件及其应用
java·开发语言·界面编程
Cachel wood43 分钟前
python round四舍五入和decimal库精确四舍五入
java·linux·前端·数据库·vue.js·python·前端框架
Code哈哈笑1 小时前
【Java 学习】深度剖析Java多态:从向上转型到向下转型,解锁动态绑定的奥秘,让代码更优雅灵活
java·开发语言·学习
gb42152871 小时前
springboot中Jackson库和jsonpath库的区别和联系。
java·spring boot·后端
程序猿进阶1 小时前
深入解析 Spring WebFlux:原理与应用
java·开发语言·后端·spring·面试·架构·springboot
zfoo-framework1 小时前
【jenkins插件】
java
风_流沙1 小时前
java 对ElasticSearch数据库操作封装工具类(对你是否适用嘞)
java·数据库·elasticsearch
ProtonBase2 小时前
如何从 0 到 1 ,打造全新一代分布式数据架构
java·网络·数据库·数据仓库·分布式·云原生·架构
乐之者v2 小时前
leetCode43.字符串相乘
java·数据结构·算法