底子知识
ApplicationContextInitializer 如何使用 ?
- IOC 容器对象创建完成后执行 , 常用于情况属性注册
- 自定义类 , 实现 ApplicationContextInitializer 接口
initialize 方法什么时间执行 ?
- 在 META-INF/spring.factories 配置文件中配置自定义的类
ApplicationListener 如何使用 ?
- IOC 容器发布事件之后执行 , 通常用于资源加载 , 定时任务发布等
- 自定义类 , 实现 ApplicationListener 接口
onApplicationEvent 方法什么时间执行 ?
- 在 META-INF/spring.factories 配置文件中配置自定义的类
BeanFactory 的作用 ?
- ApplicationConfigServletServerApplicationContext
- DefaultListableBeanFactory
BeanFactory 常见的两个实现 ?
- Bean 容器的根接口 , 提供 Bean 对象的创建、配置、依赖注入等功能
面试题
Q:SpringBoot 启动流程
答:SpringBoot 启动,其本质就是加载各种配置信息,然后初始化 IOC 容器并返回。
在其启动的过程中会做这么几个变乱
起首,当我们在启动类执行 SpringApplication.run 这行代码的时间,在它的方法内部实在会做两个变乱
- 1. 创建 SpringApplication 对象;
- 2. 执行 run 方法。
其次,在创建 SpringApplication 对象的时间,在它的构造方法内部紧张做 3 个变乱。
- 1. 确认 web 应用类型,一样寻常情况下是 Servlet 类型,这种类型的应用,将来会自动启动一个 tomcat
- 2. 从 spring.factories 配置文件中,加载默认的 ApplicationContextInitializer 和 ApplicationListener
- 3. 记载当前应用的主启动类,将来做包扫描使用
末了,对象创建好了以后,再调用该对象的 run 方法,在 run 方法的内部紧张做 4 个变乱
- 1. 准备 Environment 对象,它里面会封装一些当前应用运行情况的参数,好比情况变量等等
- 2. 实例化容器,这里仅仅是创建 ApplicationContext 对象
- 3. 容器创建好了以后,会为容器做一些准备工作,好比为容器设置 Environment 、 BeanFactoryPostProcessor 后置处理器,而且加载主类对应的 Definition
- 4. 刷新容器,就是我们常说的 referesh ,在这里会真正的创建 Bean 实例
总:实在 SpringBoot 启动的时间核心就两步,创建 SpringApplication 对象以及 run 方法的调用,在run 方法中会真正的实例化容器,并创建容器中需要的 Bean 实例,终极返回
Q:IOC 容器的初始化流程
答 : IOC 容器的初始化,核心工作是在 AbstractApplicationContext.refresh 方法中完成的。
在 refresh 方法中紧张做了这么几件事
- 1. 准备 BeanFactory ,在这一块需要给 BeanFacory 设置许多属性,好比类加载器、 Environment 等
- 2. 执行 BeanFactory 后置处理器,这一阶段会扫描要放入到容器中的 Bean 信息,得到对应的 BeanDefinition (留意,这里只扫描,不创建)
- 3. 是注册 BeanPostProcesor ,我们自定义的 BeanPostProcessor 就是在这一个阶段被加载的 , 将来 Bean 对象实例化好后需要用到
- 4. 启动 tomcat
- 5. 实例化容器中实例化非懒加载的单例 Bean, 这里需要说的是,多例 Bean 和懒加载的 Bean 不会在这个阶段实例化,将来用到的时间再创建
- 6. 当容器初始化完毕后,再做一些扫尾工作,好比清除缓存等
总:在 IOC 容器初始化的的过程中,起首得准备并执行 BeanFactory 后置处理器,其次得注册 Bean 后置处理器 , 并启动 tomcat ,末了需要借助于 BeanFactory 完成 Bean 的实例化
Q:Bean 生命周期
答:Bean 的生命周期总的来说有 4 个阶段,分别有创建对象,初始化对象,使用对象以及烧毁对象,而且这些工作大部门是交给 Bean 工厂的 doCreateBean 方法完成的。
起首,在创建对象阶段,先调用构造方法实例化对象,对象有了后会添补该对象的内容,实在就是处理依赖注入
其次,对象创建完毕后,需要做一些初始化的操纵,在这里涉及到几个扩展点。
- 1. 执行 Aware 感知接口的回调方法
- 2. 执行 Bean 后置处理器的 postProcessBeforeInitialization 方法
- 3. 执行 InitializingBean 接口的回调,在这一步如果 Bean 中有标注了 @PostConstruct 注解的方法,会先执行它
- 4. 执行 Bean 后置处理器的 postProcessAfterInitialization
把这些扩展点都执行完, Bean 的初始化就完成了
接下来,在使用阶段就是步调员从容器中获取该 Bean 使用即可
末了,在容器烧毁之前,会先烧毁对象,此时会执行 DisposableBean 接口的回调,这一步如果 Bean 中有标注了@PreDestroy 接口的函数,会先执行它
总:简单总结一下, Bean 的生命周期共包罗四个阶段(创建对象,初始化对象,使用对象以及烧毁对象),其中初始化对象和烧毁对象我们步调员可以通过一些扩展点执行自己的代码
Q:Bean 循环依赖
答: Bean 的循环依赖指的是 A 依赖 B , B 又依赖 A 这样的依赖闭环问题,在 Spring 中,通过三个对象缓存区来解决循环依赖问题,这三个缓存区被定义到了 DefaultSingletonBeanRegistry 中,分别是 singletonObjects 用来存储创建完毕的
Bean , earlySingletonObjecs 用来存储未完成依赖注入的 Bean ,还有 SingletonFactories 用来存储创建 Bean 的ObjectFactory 。如果说如今 A 依赖 B , B 依赖 A ,整个 Bean 的创建过程是这样的:
- 1.调用 A 的构造方法实例化 A ,当前的 A 还没有处理依赖注入,暂且把它称为半成品,此时会把半成品 A 封装到一个 ObjectFactory 中,并存储到 springFactories 缓存区
- 2.要处理 A 的依赖注入了,由于此时还没有 B ,以是得先实例化一个 B ,同样的,半成品 B 也会被封装到ObjectFactory 中,并存储到 springFactory 缓存区
- 3.要处理 B 的依赖注入了,此时会找到 springFactories 中 A 对应的 ObjecFactory, 调用它的 getObject方法得到刚才实例化的半成品 A( 如果需要代理对象 , 则会自动创建代理对象 , 将来得到的就是代理对象 ) ,把得到的半成品 A注入给 B ,并同时会把半成品 A 存入到 earlySingletonObjects 中,将来如果还有其他的类循环依赖了 A ,就可以直接从earlySingletonObjects 中找到它了,那么此时 springFactories 中创建 A ObjectFactory 也可以删除了
- 4.B 的依赖注入处理完了后, B 就创建完毕了,就可以把 B 的对象存入到 singletonObjects 中了,并同时删撤消 springFactories 中创建 B 的 ObjectFactory
- 5.B 创建完毕后,就可以继承处理 A 的依赖注入了,把 B 注入给 A ,此时 A 也创建完毕了,就可以把 A 的对象存储到singletonObjects 中,并同时删撤消 earlySingletonObjects 中的半成品 A
截此为止, A 和 B 对象全部创建完毕,并存储到了 singletonObjects 中,将来通过容器获取对象,都是从singletonObejcts 中获取
总:总结起来还是一句话,借助于 DefaultSingletonBeanRegistry 的三个缓存区可以解决循环依赖问题
Q:SpringMvc 执行流程
答 : 使用了 SpringMvc 后,全部的哀求都需要经过 DispatcherServlet 前端控制器,该类中提供了一个 doDispatch 方法,有关哀求处理和效果响应的全部流程都在该方法中完成
- 1.借助于 HandlerMapping 处理器映射器得到处理器执行链,里面封装了 HandlerMethod 代表目标Controller 的方法,同时还通过一个集合记载了要执行的拦截器
- 2.会根据 HandlerMethod 获取对应的 HandlerAdapter 处理器适配器,里面封装了参数剖析器以及效果处理器
- 3.执行拦截器的 preHandle 方法
- 4.通过 HandlerAdapter 处理器适配器执行目标 Controller 的方法,在这个过程中会通过参数剖析器和效果处理器分别剖析浏览器提交的数据以及处理 Controller 方法返回的效果
- 5.执行拦截器的 postHandle 方法
- 6.处理响应,在这个过程中如果有非常抛出,会执行非常的逻辑,这里还会执行全局非常处理器的逻辑,并通过视图剖析器 ViewResolver 剖析视图,再渲染视图,末了再执行拦截器的 afterCompletion
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |