【面试专题】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 组件扫描

相关推荐
myloveasuka几秒前
[Java]包装类
java·开发语言
myloveasuka3 分钟前
时间相关类
java·开发语言
青火coding4 分钟前
Embedding是什么?从文本转向量
java·机器学习·ai·embedding
6+h5 分钟前
【java IO】转换流 + 对象流 + 序列化详解
java·开发语言
一棵树73515 分钟前
Springboot项目常用工具对比总结
java·spring boot·后端
IT痴者9 分钟前
Kotlin 开发注意事项(Android Java 开发者转型指南)
android·java·kotlin
老虎06279 分钟前
Spring mysql 网络接口( HTTP 方法与增删改查, Spring MVC Controller 接收参数的常用注解与参数传递方式)
mysql·spring·http
wuqingshun31415911 分钟前
产生死锁的四个必要条件
java·jvm
青槿吖11 分钟前
第二篇:Spring MVC进阶:注解、返回值与参数接收的花式玩法
java·开发语言·后端·mysql·spring·mvc·mybatis
共享家952712 分钟前
Java入门(抽象类 与 接口)
java·开发语言