SpringBoot面试题整理(1)

面试整理

前置知识

  1. ApplicationContextInitializer
  2. ApplicationListener
  3. BeanFactory
  4. BeanDefinition
  5. BeanFactoryPostProcessor
  6. Aware
  7. InitializingBean/DisposableBean
  8. BeanPostProcessor
面试题
  1. SpringBoot启动流程
  2. IOC容器初始化流程
  3. Bean声明周期
  4. Bean循环依赖
  5. SpringMVC执行流程
ApplicationContextInitializer
  • IOC容器对象创建完成后执行,可以对上下文环境做一些操作,例如运行环境属性注册等
  • 如何使用
    1. 自定义,实现ApplicationContextInitializer接口
    2. 在MATA-INF/spring.factories配置文件中配置自定义的类
  • initialize方法什么时候执行
    • IOC容器对象创建完成后执行,常用语环境属性注册
ApplicationListener
  • 如何使用
    • 自定义类,实现ApplicationListener接口
    • 在META-INF/spring-factories配置文件中配置自定义的类
  • 什么时候执行
    • IOC容器发布事件后执行,通常用于资源加载,定时任务发布
BeanFactory
  • Bean容器的根接口,提供Bean对象的创建、配置、依赖注入等功能

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

  • ApplicationConfigServletServerApplicationContext->DefaultListableBeanFactory
BeanDefinition
  • 用于描述Bean,包括Bean的名称,Bean的属性,Bean的行为,实现的接口,添加的注解等,Spring中,Bean在创建之前,都需要封装成对应的BeanDefinition,然后根据BeanFinition进一步创建Bean对象

在这里插入图片描述

在这里插入图片描述

BeanFactoryPostProcessor
  • Bean工厂后置处理器,当BeanFactory准备好了后(Bean初始化前),会调用该接口的postProcessBeanFactory方法,经常用于新增BeanDefinition
实现类名作用
ConfigurationClassPostProcessor扫描启动类下所在包下的注解
ServletComponentRegisteringPostProcessor扫描@WebServler、@WebFilter、@WebListener
CachingMetadataReaderFactoryPostProcessor配置ConfiguraitonClassPostProcessor
ConfigurationWarningsPostProcessor配置警告提示

在这里插入图片描述

Aware
  • 感知接口,Spring提供的一种机制,通过实现该接口,重写方法,可以感知Spring应用程序执行过程中的一些变化。Spring会判断出当前的Bean有没有实现Aware接口,如果实现了,会在特定的时机回调接口对应的方法

    子接口名作用
    BeanNameAwareBean名称的感知接口
    BeanClassLoaderAwareBean类加载器的感知接口
    BeanFactoryAwareBean工厂的感知接口

    在这里插入图片描述

InitializingBean/DisposableBean
  • 初始化接口,当Bean被实例化好后,会回调里面的函数,经常用于做一些加载资源的工作

  • 销毁接口,当Bean被销毁执之前,会回调里面的函数,经常用于做一些释放资源的工作

    在这里插入图片描述

BeanPostProcessor
  • Bean的后置处理器,当Bean对象初始化之前以及初始化之后,会回调该接口对应的方法
    • postProcessBeforeInitialization:Bean对象初始化之前调用
    • postProcessAfterInitialization:Bean对象初始化之后调用
实现类名作用
AutowiredAnnotationBeanPostProcessor用来完成依赖注入
AbstractAutoProxyCreator用来完成代理对象的创建
AbstractAdvisingBeanPostProcessor将Aop中的通知作用于特定的Bean上

在这里插入图片描述

面试题

SpringBoot启动流程

  • new SpringApplication()
    1. 确认web应用的类型
    2. 加载ApplicationContextInitializer
    3. 加载ApplicationListener
    4. 记录主启动类
  • run()
    1. 准备环境对象Environment,用于加载系统属性等等
    2. 打印Banner
    3. 实例化容器Context
    4. 准备容器,为容器设置Environment、BeanFactoryPostProcessor,并加载主类对应的BeanDefinition
    5. 刷新容器(创建Bean实例)
    6. 返回容器

在这里插入图片描述

在这里插入图片描述

总结:

问:请聊聊SpringBoot启动的过程?

总:SpringBoot启动,其本质就是加载各种配置信息,然后初始化IOC容器并返回

分:在其启动的过程中会做这么几件事情:

​ 首先,当我们在启动类执行SpringApplication.run这行代码的时候,在它的方法内部其实会做两件事

​ 1.创建SpringApplication对象

​ 2.执行run方法

​ 其次,在创建StringApplication对象的时候,在它的构造方法内部主要做3件事情

​ 1.确认web应用类型,一般情况下是Servlet类型,这种类型的应用,将来会自动启动一个tomcat

​ 2.从spring.factories配置文件中,加载默认的ApplicationContextInitializer和ApplicationListener

​ 3.记录当前应用的主启动类,将来做包的扫描使用

​ 最后,对象创建好了以后,在调用该对象的run方法,在run方法的内部主要做4个事情

​ 1.准备Environment对象,它里面会封装一些当前应用运行环境的参数,比如环境变量等等

​ 2.实例化容器,这里仅仅是创建ApplicationContext对象

​ 3.容器创建好了以后,会为容器做一些准备工作,比如为容器设置Environment、 BeanFactoryPostProcessor后置处理器,并且加载主类对应的Definition

​ 4.刷新容器,就是我们常说的refresh,在这里会真正的创建Bean实例

总:总结一下我刚才说的,其实SpringBoot启动的时候核心就两步,创建SpringApplication对象以及run方法的调用,在run方法中会真正的实例化容器,并创建容器中需要的Bean实例,最终返回

IOC容器初始化流程

  • AbstractApplicationContext.refresh()
  1. 准备BeanFactory(DefaultListableBeanFactory)

    设置ClassLoader

    设置Environment

  2. 扫描要放入容器中的Bean,得到对应的BeanDefinition(只扫描,并不创建)

  3. 注册BeanPostProcessor

  4. 处理国际化

  5. 初始化事件多播器ApplicationEventMulticaster

  6. 启动Tomcat

  7. 绑定事件监听器和事件多播器

  8. 实例化非懒加载的单例Bean

  9. 扫尾工作,比如清空实例化时占用的缓存等

在这里插入图片描述

总结

问:请聊一聊IOC容器初始化的流程?

总:IOC容器的初始化,核心工作时在AbstractApplicationContext.refresh方法中完成的

分:在refresh方法中主要做了这么几件事

​ 1.准备BeanFactory,在这个一块需要给BeanFactory设置很多属性,比如类加载器、Environment等

​ 2.执行BeanFactory后置处理器,这一阶段会扫描要放入到容器中的Bean信息,得到应用的BeanDefinition(注意,这里只扫描不创建)

​ 3.是注册BeanPostProcessor,我们自定义的BeanPostProcessor就是在这个阶段被加载的,将来Bean地域性实例化好后需要用到的时候再创建

​ 4.启动tomcat

​ 5.实例化容器中实例化非懒加载的单例Bean,这里需要说的事,多例Bean和懒加载的Bean不会在这个阶段实例化,将来用到的时候再创建

​ 6.当容器事出花完毕后,再做一些扫尾工作,比如清除缓存等

总:简单总结一下,在IOC容器初始化的过程中,首先得准备并执行BeanFactory后置处理器,其次得注册Bean后置处理器,并启动tomcat,最后需要借助于BeanFactory完成Bean的实例化

Bean循环依赖

  • Bean循环依赖是指依赖闭环的问题

在这里插入图片描述

在这里插入图片描述

总结

问:请聊一聊Bean循环依赖是怎么实现的?

总:Bean的循环依赖指的是A依赖B,B又依赖A这样的依赖闭环问题。在Spring中,通过三个对象存储区来解决循环依赖问题,这三个缓存区被定义到了DefaultSingletonBeanRegistry中,分别是singletonObjects用来存储创建完毕的Bean,earlySingletonObjects用来存储未完成依赖注入的Bean,还有SingletonFactories用来存储创建Bean的ObjectFactory。假如说现在A依赖B,B依赖A,整个创建Bean的过程是这样的:

分:

​ 首先,调用A的构造方法实例化A,当前的A还没有处理依赖注入,暂且把它称为半成品,此时会把半成品A封装到一个ObjectFactory中,并存储到springFactories缓存区

​ 接下来,要处理A的依赖注入了,由于此时还没有B,所以得先实例化一个B,同样的,半成品B也会被封装到ObjectFactory中,并存储到springFactories缓存区

​ 紧接着,要处理B的依赖注入了,此时会找到springFactories中A对应的objectFactorty,调用它的getObject方法得到刚才实例化的半成品A(如果需要代理对象,则会自动创建代理对象),把得到的半成品A注入给B,并同时会把半成品A存入到earlySingletonObjects中,将来如果还有其他的类循环依赖了A,就可以直接从earlySingletonObjects中找到它了,那么此时springFactories中创建A的ObjectFactory也可以删除了

​ 至此,B的依赖注入处理完了后,就可以继续处理A的依赖注入了,把B注入给A,此时A也创建完了,就可以把A的对象存储到singletonObjects中,并同时删除掉earlySingletonObjects中的半成品A

​ 截此为止,A和B对象全部创建完毕,并存储到了singletonObjects中,将来通过容器获取对象,都是从singletonObjects中获取

总:总结起来就是一句话,借助于DefaultSingletonBeanRegistry的三个缓存区可以解决循环依赖问题

SpringMVC执行流程

  • Mvc接收到请求开始,到给浏览器做出响应之间的过程

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

总结面试

问:请聊一聊SpringMVC的执行流程?

总:

​ 使用了SpringMvc后,所有的请求都需要经过DispatcherServlet前端控制器,该类中提供了一个doDispatch方法,有关请求处理和结果响应的所有流程都在该方法中完成

分:

​ 首先,借助于HandlerMapping处理器映射器得到处理器执行链,里面封装了HandlerMethod代表目标Controller的方法,同时还通过一个集合记录了要执行的拦截器

​ 接下来,会根据HandlerMethod获取对应的HandlerAdapter处理器适配器,里面封装了参数解析器以及结果处理器

​ 然后,执行拦截器的perHandler方法

​ 接下来是核心,通过HandlerAdapter处理器适配器执行目标Controller方法,在这个过程中会通过参数解析器和结果处理器分别解析浏览器提交的数据以及处理Controller方法返回的结果

​ 然后,执行拦截器的postHandle方法

​ 最后处理响应,在这个过程中如果有异常抛出,会执行异常的逻辑,这里还会执行全局异常处理器的逻辑,并通过视图解析器viewResolver解析视图,再渲染视图,最后再执行拦截器的afterCompletion

​ 然后,执行拦截器的perHandler方法

​ 接下来是核心,通过HandlerAdapter处理器适配器执行目标Controller方法,在这个过程中会通过参数解析器和结果处理器分别解析浏览器提交的数据以及处理Controller方法返回的结果

​ 然后,执行拦截器的postHandle方法

​ 最后处理响应,在这个过程中如果有异常抛出,会执行异常的逻辑,这里还会执行全局异常处理器的逻辑,并通过视图解析器viewResolver解析视图,再渲染视图,最后再执行拦截器的afterCompletion

  • 26
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值