• 【面试专题】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对象已经创建完成,则可以直接注入BA创建成功存入一次缓存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 依赖:

    1. org.springframework.boot
    2. spring-boot-starter-web

    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。

    1. package com.lanqiaoyun.springbootdemo;
    2. import org.springframework.boot.SpringApplication;
    3. import org.springframework.boot.autoconfigure.SpringBootApplication;
    4. @SpringBootApplication
    5. public class SpringbootdemoApplication {
    6. public static void main(String[] args) {
    7. SpringApplication.run(SpringbootdemoApplication.class, args);
    8. }
    9. }

    @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 组件扫描

     

  • 相关阅读:
    【运维】-gitlab docker-compose部署,并进行备份
    2022年,有哪些适合普通人的风口项目?
    软件测试入门之接口测试
    ⑤、企业快速开发平台Spring Cloud之HTML <head>
    Grafana alert预警+钉钉通知
    JAVA工程师面试专题-《Redis》篇
    著名童星刘佳琪深圳市中心举办个人Live音乐汇专辑发布会圆满成功
    C++标准模板(STL)- 类型支持 (数值极限,round_style,is_iec559,is_bounded)
    一维时间序列信号的改进小波降噪方法(MATLAB R2021B)
    【华为OD机试真题 python】最大社交距离【2022 Q4 | 200分】
  • 原文地址:https://blog.csdn.net/Javascript_tsj/article/details/132657022