Spring源码启动过程以及拓展点

容器启动过程

  1. 第一步先调用this();构造方法,这时父类构造器会初始化容器的 beanFactory 属性,属性为DefaultListableBeanFactory,带有存储BeanDefinition 和单例 bean 的功能
  • 新建一个注解Bean定义读取器 new AnnotatedBeanDefinitionReader(this); 这个读取器主要是初始化环境变量,以及注册 一些创世纪的 BeanDefinition 【例如:ConfigurationClassPostProcessor、AutowiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor、EventListenerMethodProcessor、DefaultEventListenerFactory】
  • 新建一个类路径扫描器ClassPathBeanDefinitionScanner
  1. 容器调用register(componentClasses);把启动类注册成BeanDefinition放入到容器中
  2. 启动Spring,调用 refresh() 方法去刷新容器
  3. prepareRefresh() 准备刷新方法,没有做什么重要的事情,主要是设置了下容器的启动状态
  4. 调用obtainFreshBeanFactory();获取到容器的工厂,DefaultListableBeanFactory
  5. 调用prepareBeanFactory(beanFactory)
  • 设置容器的类加载器
  • 设置Spring容器中需要忽略的set方法
  • ResourceEditorRegistrar注册资源编辑器,当Bean初始化的时候,构造器上需要注入Spring资源相关的Bean时,由该类注入
  • 注册三个BeanPostProcessor到容器中【ApplicationContextAwareProcessor (会在Bean初始化前,调用,例如ApplicationContextAware接口,会注入ApplicationContext容器到类中)、LoadTimeWeaverAwareProcessor (织入Bean后置处理器)】
  1. 调用postProcessBeanFactory(beanFactory);留给子类来设置BeanFactory
  2. 调用invokeBeanFactoryPostProcessors(beanFactory) 方法
  • 第一次调用已经初始化过的 BeanDefinitionRegistryPostProcessor 类的 registryProcessor.postProcessBeanDefinitionRegistry(registry) 方法,基本上不会有,除非自己在前面步骤设置过
  • 第二次调用实现了PriorityOrdered的 BeanDefinitionRegistryPostProcessor 接口的类的.postProcessBeanDefinitionRegistry(registry) 方法,一般只会有 ConfigurationClassPostProcessor 类,这个类在 1.a 步骤中被注册成BeanDefinition
    • ConfigurationClassPostProcessor 去解析配置类,如果类是由 @Configuration 注解的类,则为 full 配置类,其他则为 lite 配置类【full配置类,会生成CGLib动态代理,@Bean方法只会调用一次,下次就直接获取上次的对象;Lite配置类,则生成普通类】
    • 生成Configuration解析器,会去解析 @ComponentScan 注解包下所有的类,并且会循环调用,知道把所有需要解析成 BeanDefinition 的类都注册进来 (包括@Component、@Import、@ImportResource这些注解)
    • 会解析配置类中有多个@Bean
  • 调用实现了 Ordered 的 BeanDefinitionRegistryPostProcessor 接口的类 的 postProcessBeanDefinitionRegistry(registry) 方法
  • 调用没有实现 PriorityOrdered、Ordered 的 BeanDefinitionRegistryPostProcessor 接口的类 的 postProcessBeanDefinitionRegistry(registry) 方法
  • 然后调用之前所有 BeanDefinitionRegistryPostProcessor 类的 postProcessBeanFactory(beanFactory) 方法,会调用 ConfigurationClassPostProcessor 类
    • ConfigurationClassPostProcessor. postProcessBeanFactory(beanFactory) 会把Full配置类的BeanDefinition 的类型设置成CGLIB的动态代理类型,初始化时,就是CGLIB动态代理
  • 调用实现了PriorityOrdered 的 BeanFactoryPostProcessor 类的 postProcessBeanFactory(beanFactory) 方法
  • 调用实现了Ordered 的 BeanFactoryPostProcessor 类的 postProcessBeanFactory(beanFactory) 方法
  • 调用没有实现 PriorityOrdered、Ordered 的 BeanFactoryPostProcessor 类的 postProcessBeanFactory(beanFactory) 方法
    • EventListenerMethodProcessor (会在所有Bean都实例化完成后,解析Bean中是否带有@EventListener方法,如果有,则会利用EventListenerFactory,生成一个ApplicationListener放入容器中)默认实例化出所有 EventListenerFactory 的类
  1. 调用registerBeanPostProcessors(beanFactory);注册Bean的后置处理器到容器中
  • 主要是两个后置处理器 internalAutowiredAnnotationProcessor、internalCommonAnnotationProcessor
  • 会按照优先PriorityOrdered然后Ordered,最后都没实现的BeanPostProcess类的顺序放入到容器中
  • 最后放入ApplicationListenerDetector
  1. 调用 initMessageSource(); 初始化国际化 ,一般是DelegatingMessageSource对象
  2. 调用 initApplicationEventMulticaster(); 设置容器的事件多播器为 SimpleApplicationEventMulticaster
  3. 调用 onRefresh(); 方法,Springboot 就是调用这个方法来启动tomcat容器的
  4. 调用registerListeners();注册事件监听器到容器中,并且如果有早期事件类型,则在容器事件广播器未生成好之前发布事件
  5. 调用 finishBeanFactoryInitialization(beanFactory); 实例化非懒加载的 Bean
  • 先判断是否有conversionService类型的Bean,如果有,则需要转化生成
  • 实例化LoadTimeWeaverAware对象
  • 实例化Bean
    • 实例化之前会先调用 InstantiationAwareBeanPostProcessor 接口的 postProcessBeforeInstantiation 方法,这个时候可以自己初始化出来,返回给容器
    • 实例化对象,这个时候有个策略 getInstantiationStrategy().instantiate(mbd, beanName, this); 如果是之前设置了CGLIB动态代理,这里生成的是代理后的对象
    • 遍历调用MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition()方法
      • 这里会调用 AutowiredAnnotationBeanPostProcessor 的 postProcessMergedBeanDefinition 找到所有的 @Autowired或者@Value 注解的方法或属性,为后续IOC,依赖注入做准备
    • 自动注入属性
    • 生成后先遍历所有的 BeanPostProcessor.postProcessBeforeInitialization(Object bean, String beanName) 方法,这个方法可以重新返回一个新的Bean
      • 所有的 Aware 拓展点在这里实现,通过 ApplicationContextAwareProcessor 类,实现了EnvironmentAware、EmbeddedValueResolverAware、ResourceLoaderAware、ApplicationEventPublisherAware、MessageSourceAware、ApplicationContextAware、ApplicationStartupAware等类在这一步注入
    • 实例化Bean,如果Bean实现了 InitializingBean 接口的Bean,会调用它的 afterPropertiesSet 方法
    • 遍历所有的 BeanPostProcessor.postProcessAfterInitialization(Object bean, String beanName) 方法,这个方法可以重新返回一个新的Bean
  • 所有Bean实例化完成后 便利所有bean,调用实现了 SmartInitializingSingleton 接口类的afterSingletonsInstantiated方法
  1. 最后调用 finishRefresh(),发布容器 publishEvent(new ContextRefreshedEvent(this)); 刷新完成事件

Spring所有拓展点以及顺序

  1. 实现了 BeanDefinitionRegistryPostProcessor 接口的类,调用 postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) 方法,可以获取到Bean定义的注册器,去注册BeanDefinition,调用会按照先调用实现了 PriorityOrdered 接口 再调用 Ordered 接口 最后再调用没有实现 PriorityOrdered 接口 、 Ordered 接口 的 BeanDefinitionRegistryPostProcessor 类
  2. 实现了 BeanFactoryPostProcessor 接口的类,调用 postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) 方法,可以获取到Bean定义的注册器,去注册BeanDefinition,调用会优先调用实现了BeanDefinitionRegistryPostProcessor 接口的类的 postProcessBeanFactory方法,再按照先调用实现了 PriorityOrdered 接口 再调用 Ordered 接口 最后再调用没有实现 PriorityOrdered 接口 、 Ordered 接口 的 BeanDefinitionRegistryPostProcessor 类
  3. 实现了 InstantiationAwareBeanPostProcessor 接口的类,调用 postProcessBeforeInstantiation(Class<?> beanClass, String beanName) 方法,这个方法可以直接自己初始化出来Bean
  4. 实现了 MergedBeanDefinitionPostProcessor 接口的类,调用 postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) 方法;这个时候Bean已经初始化了,但是属性还没有注入;AutowiredAnnotationBeanPostProcessor 的 postProcessMergedBeanDefinition 找到所有的 @Autowired或者@Value 注解的方法或属性,为后续IOC,依赖注入做准备
  5. 实现了EnvironmentAware、EmbeddedValueResolverAware、ResourceLoaderAware、ApplicationEventPublisherAware、MessageSourceAware、ApplicationContextAware、ApplicationStartupAware的类,会在这一步注入相关环境变量属性
  6. 实现了 BeanPostProcessor 接口的类,调用 postProcessBeforeInitialization(Object bean, String beanName) 方法,这一步Bean已经实例化了,并且属性已经注入了,也可以通过这个拓展来修改对象
  7. 实现了 InitializingBean 接口的Bean,会调用对象的 afterSingletonsInstantiated() 方法。一般作为对象初始化完成调用的拓展点
  8. 实现了 BeanPostProcessor 接口的类,调用 postProcessAfterInitialization(Object bean, String beanName) 方法,这一步Bean已经实例化了,并且属性已经注入了,也可以通过这个拓展来修改对象
  9. 调用实现了 SmartInitializingSingleton 接口类的 afterSingletonsInstantiated() 方法;这个时候所有的Bean已经实例化完成,后续加入的Bean不会受Bean工厂的后置处理器影响
  10. 监听Spring容器启动事件 ContextRefreshedEvent
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容