Spring原理篇(10)--Spring系列IOC小总结;Spring的启动原理;不得了;当初我某个同学把这一块东西搞得明明白白的; 不管是工作上遇到的问题;还是面试中遇到的问题都不在话下

这两行代码其实并不难; 同学们可以自己点进去看一下; 别看到代码多就慌;

register(componentClasses);

重点看这行代码 重点!!重点!!重点!!!

refresh();

}

refresh

===================================================================

refresh():加载或刷新持久化的 配置,可能是XML文件、属性文件或关系数据库中存储的。由于这是一个启动方法,如果失败,它应 该销毁已经创建的单例,以避免暂用资源。换句话说,在调用该方法之后,应该实例化所有的单例, 或者根本不实例化单例 。

ApplicationContext关闭之后不代表JVM也关闭了,ApplicationContext是 属于JVM的,说白了ApplicationContext也是JVM中的一个对象。

在Spring的设计中,也提供可以刷新的ApplicationContext和不可以刷新的ApplicationContext

可刷新的

AbstractRefreshableApplicationContext extends AbstractApplicationContext

不可刷新的

GenericApplicationContext extends AbstractApplicationContext

AnnotationConfigApplicationContext继承的是GenericApplicationContext,所以它是不能刷新 的。 AnnotationConfigWebApplicationContext继承的是 AbstractRefreshableWebApplicationContext,所以它是可以刷的。 上面说的不能刷新是指不能重复刷新,只能调用一次refresh方法,第二次时会报错。

一下就是关键重点代码; 我前几篇文章 全部都有写; 但是可能写得不够详细;这里我们再从新写一次;

里面的代码我就不再继续累赘; 因为里面代码 我们基本上都看过一次;

public void refresh() throws BeansException, IllegalStateException {

synchronized (this.startupShutdownMonitor) {

StartupStep contextRefresh = this.applicationStartup.start(“spring.context.refresh”);


这里是往BeanFactory 继续set 其他属性 并且里面有一个方法是:

–initPropertySources() 该方法就是初始化property 里面的属性;

有一些属性是可以设置成必须注入的属性 我们以前再整合SpringMVC的时候 再web.xml里面就有配置;

直白一点就是一些Key Value键值对;

以下就是详细:

1记录启动时间

2可以允许子容器设置一些内容到Environment中

3验证Environment中是否包括了必须要有的属性

prepareRefresh(); --源码


进行BeanFactory的refresh,在这里会去调用子类的 refreshBeanFactory方法,

具体子类是怎么刷新的得看子类,然后再调用子类的 getBeanFactory方法,

重新得到一个BeanFactory

ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); --源码


prepareBeanFactory(beanFactory);–源码

1:设置beanFactory的类加载器

2:设置表达式解析器:StandardBeanExpressionResolver,用来解析Spring中的表达式

3:添加PropertyEditorRegistrar:ResourceEditorRegistrar,PropertyEditor类型转化器注 册器,用来注册一些默认的PropertyEditor

4:添加一个Bean的后置处理器:ApplicationContextAwareProcessor,是一个 BeanPostProcessor,用来执行EnvironmentAware、ApplicationEventPublisherAware 等回调方法

5:添加ignoredDependencyInterface:可以向这个属性中添加一些接口,

如果某个类实现 了这个接口,并且这个类中的某些set方法在接口中也存在,

那么这个set方法在自动注入的 时候是不会执行的,比如EnvironmentAware这个接口,

如果某个类实现了这个接口,那么 就必须实现它的setEnvironment方法,

而这是一个set方法,和Spring中的autowire是冲突 的,

那么Spring在自动注入时是不会调用setEnvironment方法的,

而是等到回调Aware接 口时再来调用(注意,这个功能仅限于xml的autowire,@Autowired注解是忽略这个属性 的){

a. EnvironmentAware

b. EmbeddedValueResolverAware

c. ResourceLoaderAware

d. ApplicationEventPublisherAware

e. MessageSourceAware

f. ApplicationContextAware

g 另外其实在构造BeanFactory的时候就已经提前添加了另外三个:

h. BeanNameAware

i. BeanClassLoaderAware

j. BeanFactoryAware

}

6:添加resolvableDependencies:在byType进行依赖注入时,会先从这个属性中根据类型 找bean{

a. BeanFactory.class:当前BeanFactory对象

b. ResourceLoader.class:当前ApplicationContext对象

c. ApplicationEventPublisher.class:当前ApplicationContext对象

d. ApplicationContext.class:当前ApplicationContext对象

}

7:添加一个Bean的后置处理器:ApplicationListenerDetector,

是一个 BeanPostProcessor,用来判断某个Bean是不是ApplicationListener,

如果是则把这个 Bean添加到ApplicationContext中去,

注意一个ApplicationListener只能是单例的

8: 添加一个Bean的后置处理器:LoadTimeWeaverAwareProcessor,

是一个 BeanPostProcessor,用来判断某个Bean是不是实现了LoadTimeWeaverAware接口,

如果实现了则把ApplicationContext中的loadTimeWeaver回调setLoadTimeWeaver方法

设置给该Bean。

9:添加一些单例bean到单例池{

a. “environment”:Environment对象

b. “systemProperties”:System.getProperties()返回的Map对象

c. “systemEnvironment”:System.getenv()返回的Map对象

}


try {

提供给AbstractApplicationContext的子类进行扩 展,具体的子类,可以继续向BeanFactory中再添加一些东西

postProcessBeanFactory(beanFactory); --源码


记录beanPostProcess 创建时间

StartupStep beanPostProcess = this.applicationStartup.start(“spring.context.beans.post-process”); --源码


invokeBeanFactoryPostProcessors(beanFactory);–源码

执行BeanFactoryPostProcessor{

1:此时在BeanFactory中会存在一个BeanFactoryPostProcessor: ConfigurationClassPostProcessor,它也是一个 BeanDefinitionRegistryPostProcessor

2:从BeanFactory中找到类型为BeanDefinitionRegistryPostProcessor的beanName,也就 是ConfigurationClassPostProcessor, 然后调用BeanFactory的getBean方法得到实例 对象

3:执行**ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry()**方法:[

a. 解析AppConfig类

b. 扫描得到BeanDefinition并注册

c. 解析@Import,@Bean等注解得到BeanDefinition并注册

d. ConfigurationClassPostProcessor是如何工作的 放到下个篇章 这里留个坑

e. 在这里,我们只需要知道在这一步会去得到BeanDefinition,而这些BeanDefinition中 可能存在BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor,所以 执行完ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry()方 法后,还需要继续执行其他BeanDefinitionRegistryPostProcessor的 postProcessBeanDefinitionRegistry()方法

]

4:执行其他BeanDefinitionRegistryPostProcessor的 **postProcessBeanDefinitionRegistry()**方法

5:执行所有BeanDefinitionRegistryPostProcessor的**postProcessBeanFactory()**方法

6:从BeanFactory中找到类型为BeanFactoryPostProcessor的beanName,而这些 BeanFactoryPostProcessor包括了上面的BeanDefinitionRegistryPostProcessor

7:执行还没有执行过的BeanFactoryPostProcessor的**postProcessBeanFactory()**方法

}


因为上面的步骤完成了扫描,这个过程中程序员 可能自己定义了一些BeanPostProcessor,

在这一步就会把BeanFactory中所有的 BeanPostProcessor找出来并实例化得到一个对象,

并添加到BeanFactory中去(属性 beanPostProcessors),

最后再重新添加一个ApplicationListenerDetector对象(之前其实就添加了过,

这里是为了把ApplicationListenerDetector移动到最后)

registerBeanPostProcessors(beanFactory);–源码


到此,所有的BeanFactoryPostProcessor的逻辑都执行完了,主要做的事情就是得到 BeanDefinition并注册到BeanFactory中

beanPostProcess.end();–源码


如果BeanFactory中存在一个叫做"messageSource"的 BeanDefinition,那么就会把这个Bean对象创建出来并赋值给ApplicationContext的 messageSource属性,让ApplicationContext拥有国际化的功能

initMessageSource();–源码


如果BeanFactory中存在一个叫 做"applicationEventMulticaster"的BeanDefinition,

那么就会把这个Bean对象创建出来并 赋值给ApplicationContext的applicationEventMulticaster属性,

让ApplicationContext拥有 事件发布的功能

initApplicationEventMulticaster();–源码


提供给AbstractApplicationContext的子类进行扩展,没用

onRefresh();–源码


从BeanFactory中获取ApplicationListener类型的beanName,

然后添加 到ApplicationContext中的事件广播器applicationEventMulticaster中去,

到这一步因为 FactoryBean还没有调用getObject()方法生成Bean对象,

所以这里要在根据类型找一下 ApplicationListener,记录一下对应的beanName

registerListeners();–源码


完成BeanFactory的初始化,主要就是实例化 非懒加载的单例Bean

finishBeanFactoryInitialization(beanFactory);–源码


finishRefresh();–源码

BeanFactory的初始化完后,就到了Spring启动的最后一步了

设置ApplicationContext的lifecycleProcessor,默认情况下设置的是 DefaultLifecycleProcessor

调用lifecycleProcessor的onRefresh()方法,如果是DefaultLifecycleProcessor,那么会获取所 有类型为Lifecycle的Bean对象,然后调用它的start()方法,这就是ApplicationContext的生命 周期扩展机制

发布ContextRefreshedEvent事件

}

catch (BeansException ex) {

if (logger.isWarnEnabled()) {

logger.warn("Exception encountered during context initialization - " +

"cancelling refresh attempt: " + ex);

}

destroyBeans();

cancelRefresh(ex);

throw ex;

}

finally {

resetCommonCaches();

contextRefresh.end();

}

}

}

执行BeanFactoryPostProcessor

======================================================================================

  1. 执行通过ApplicationContext添加进来的BeanDefinitionRegistryPostProcessor的 postProcessBeanDefinitionRegistry()方法

  2. 执行BeanFactory中实现了PriorityOrdered接口的BeanDefinitionRegistryPostProcessor的 postProcessBeanDefinitionRegistry()方法

  3. 执行BeanFactory中实现了Ordered接口的BeanDefinitionRegistryPostProcessor的 postProcessBeanDefinitionRegistry()方法

  4. 执行BeanFactory中其他的BeanDefinitionRegistryPostProcessor的 postProcessBeanDefinitionRegistry()方法

  5. 执行上面所有的BeanDefinitionRegistryPostProcessor的postProcessBeanFactory()方法

  6. 执行通过ApplicationContext添加进来的BeanFactoryPostProcessor的 postProcessBeanFactory()方法

  7. 执行BeanFactory中实现了PriorityOrdered接口的BeanFactoryPostProcessor的 postProcessBeanFactory()方法

  8. 执行BeanFactory中实现了Ordered接口的BeanFactoryPostProcessor的 postProcessBeanFactory()方法

  9. 执行BeanFactory中其他的BeanFactoryPostProcessor的postProcessBeanFactory()方法

至此 Spring启动就算彻底完成;

seeyou

最后

针对最近很多人都在面试,我这边也整理了相当多的面试专题资料,也有其他大厂的面经。希望可以帮助到大家。

最新整理面试题
在这里插入图片描述

上述的面试题答案都整理成文档笔记。也还整理了一些面试资料&最新2021收集的一些大厂的面试真题

最新整理电子书

在这里插入图片描述

最新整理大厂面试文档

在这里插入图片描述

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


最后

针对最近很多人都在面试,我这边也整理了相当多的面试专题资料,也有其他大厂的面经。希望可以帮助到大家。

最新整理面试题
[外链图片转存中…(img-7c11Yo2M-1714472371780)]

上述的面试题答案都整理成文档笔记。也还整理了一些面试资料&最新2021收集的一些大厂的面试真题

最新整理电子书

[外链图片转存中…(img-jsSaOhF5-1714472371780)]

最新整理大厂面试文档

[外链图片转存中…(img-x7FelshI-1714472371781)]

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

  • 27
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值