📃个人主页:个人主页
🔥系列专栏:Java面试专题
目录
1.spring-bean的循环依赖
2.springMVC执行流程
3.Springboot自动配置原理
4.Spring框架常见的注解(Spring,SpringMVC,SpringBoot)
1.spring-bean的循环依赖
- 第一,先实例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清除
2.springMVC执行流程
①用户发送请求到前端控制器DispatcherServlet
②DispatcherServlet收到请求调用HandlerMapping(处理器映射器)。
③HandlerMapping找到具体的处理器,生成处理器对象及处理器拦截器(如果有),再一起返回给DispatcherServlet。
④DispatcherServlet调用HandlerAdapter(处理器适配器)。
⑤HandlerAdapter经过适配调用具体的处理器(Handler/Controller)。
⑥方法上添加@ResponseBody
⑦通过HttpMessageConverter来返回结果转换为JSON并响应
3.Springboot自动配置原理
什么是自动装配
Spring Boot 相比于 Spring 的一个很大进步点在于不用再手动配置一系列配置文件,Spring Boot 提供了配置应用程序和框架所需要的基本配置,这就是自动配置。本节会先通过源码介绍自动装配,并在本节最后给出总结。
Spring Boot 启动器
Spring Boot 中的一系列启动器是自动装配的最佳实践。比如当引入了一个 spring-boot-starter-web 依赖:
<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。
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 的启动类,这个注解也是自动装配的核心。
@Target
、Retention
、Documented
、Inherited
四个注解是标准的元注解,核心在于@SpringBootConfiguration
和@EnableAutoConfiguration
这两个注解。
通过继续进入注解内部,可以将@SpringBootConfiguration
和@EnableAutoConfiguration
这两个注解的结构表示出来:
- @SpringBootConfiguration : Spring Boot 的配置
- @Configuration : Spring 配置类
- @Component : Spring 的组件
- @Configuration : Spring 配置类
- @EnableAutoConfiguration : 自动配置
- @AutoConfigurationPackage : 自动配置包
- @Import({Registrar.class}) : 自动配置包注册
- @Import({AutoConfigurationImportSelector.class}) : 导入选择器
- @AutoConfigurationPackage : 自动配置包
@SpringBootConfiguration
声明了这个类为 SpringBoot 的组件,@EnableAutoConfiguration
是自动配置的核心,其中@AutoConfigurationPackage
对配置包进行了注册,AutoConfigurationImportSelector
类来进行自动装配。
继续来看看 AutoConfigurationImportSelector
这个类。
- 引入环境。
- 引入 bean 加载器。
- 引入资源加载器。
- 配置导入。
继续向下看,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容器中使用。
自动装配总结起来可以分为以下几步:
- Spring Boot 在启动的时候,从类路径下/META-INF/spring.factories 获取指定的值;
- 将这些自动配置的类导入容器,自动配置就会生效,进行自动配置!
- 以前我们需要自动配置的东西,现在 Spring Boot 帮我们做了
- 自动配置的东西都在 spring-boot-autoconfigure.jar 这个包下
- 它会把所有需要导入的组件,以类名的方式返回,这些组件就会被添加到容器;
- 容器中也会存在非常多的 xxxAutoConfiguration 的类(@Bean),就是这些类给容器中导入了这个场景需要的所有组件;并通过@Configuration 自动配置。
- 有了自动配置类,免去了我们手动编写配置文件的步骤。
4.Spring框架常见的注解(Spring,SpringMVC,SpringBoot)