Spring主要加载链路分析

包扫描

1
2
3
4
5
6
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.6.RELEASE</version>
<relativePath />
</parent>
  • application.run => prepareEnvironment 准备环境

    • 发布事件 BootstrapApplicationListener => bootstrap 会触发一个application.run
  • bootstrap的run执行完后,继续执行原application.run,也就是prepareEnvironment 处理完后,refreshContext刷新上下文

  • AbstractApplicationContext #invokeBeanFactoryPostProcessors

  • PostProcessorRegistrationDelegate #invokeBeanDefinitionRegistryPostProcessors

    • for 后置处理器 #postProcessBeanDefinitionRegistry
  • ConfigurationClassPostProcessor #processConfigBeanDefinitions

    • BeanDefinitionRegistry注册表 获取初始BeanDefinition
    • for 校验获取可用配置类,一般都是项目的启动类
    • 分析配置类 319行 parser.parse(…) => processConfigurationClass()
  • ConfigurationClassParser #doProcessConfigurationClass 289行开始根据扫描路径开始扫描包

    • 296行 ComponentScanAnnotationParser #parse 包扫描解析,根据ComponentScan注解配置对扫描器进行配置,然后执行扫描 scanner.doScan(…)
    • ClassPathBeanDefinitionScanner #doscan 通过类加载器以及配置路径,从编译后文件中获取,获取@Component相关类,不满足则过滤,最后返回全部可自动装配类
  • for 处理包扫描结果集

    • 自动装配相关类都会通过校验,主要关注以下方法

      1
      2
      3
      ConfigurationClassUtils 
      #checkConfigurationClassCandidate()
      #isConfigurationCandidate()
    • 缓存到元数据读取工厂 metadataReaderFactory

    • processConfigurationClass() 递归处理

配置类处理逻辑

  • ConfigurationClassParser #processConfigurationClass

    • 获取配置类缓存 configurationClasses
      • 已存在缓存,配置类与 @Imported 有关,则执行完相关逻辑后直接return
      • 已存在缓存,配置类与 @Imported 无关,讲配置类从缓存中去除,继续执行重新加载(具体处理原因源码中有注释)
    • 递归处理配置类及其父类 #doProcessConfigurationClass 有父类则通过方法返回值赋值,递归处理
    • 配置类放入缓存 configurationClasses
  • ConfigurationClassParser #doProcessConfigurationClass

    • 配置类是否有 @Component ,有则先递归处理内部类 #processMemberClasses

      • TODO
    • 处理 @PropertySource

    • 处理 @ComponentScan 包扫描

      • ComponentScanAnnotationParser #parse 包扫描解析,根据ComponentScan注解配置对扫描器进行配置,然后执行扫描 scanner.doScan(…)

        ClassPathBeanDefinitionScanner #doscan => #findCandidateComponents 通过类加载器以及配置路径,从编译后文件中获取。

        #isCandidateComponent(MetadataReader metadataReader) 获取可自动装配类,包括 @Component,具体看方法实现,其中includeFilters包含了@Component

      • for 处理包扫描结果集

        1. 转换成BeanDefinition

        2. 校验BeanDefinition,主要关注以下方法,一般自动装配类都会通过校验

          1
          2
          3
          ConfigurationClassUtils 
          #checkConfigurationClassCandidate()
          #isConfigurationCandidate()
        3. 通过校验后解析相应BeanDefinition #parse(String className, String beanName)

        4. 缓存到元数据读取工厂 metadataReaderFactory

        5. processConfigurationClass() 递归处理

    • 处理 @Import

      • 先通过 #getImports() 获取导入配置类,当前类上注解 => 注解上的注解,递归获取相关注解有过滤逻辑:

        1
        2
        3
        // ConfigurationClassParser
        Predicate<String> DEFAULT_EXCLUSION_FILTER = className ->
        (className.startsWith("java.lang.annotation.") || className.startsWith("org.springframework.stereotype."));
      • @import导入的配置类也会加入缓存 metadataReaderFactory

    • 处理 @ImportResource

    • 处理 @Bean

      • 获取全部 @Bean 相关方法
      • 当相关方法为复数时,且元数据是由反射生成(original instanceof StandardAnnotationMetadata)。因为反射无需,需要排序
      • 根据@Bean结果集,给配置类添加 BeanMethod
    • 处理接口默认方法

    • 处理父类

      • knownSuperclasses 缓存已处理过的父类
      • 有父类就返回父类,外层循环递归处理父类 return sourceClass.getSuperClass();
    • 没有父类返回null,结束递归 return null;

Spring事件

  • ApplicationEvent: 抽象事件类,可按需求自定义实现
  • ApplicationListener:抽象事件监听接口,其方法onApplicationEvent()是事件被驱动的入口
  • ApplicationEventPublisher: 事件发布接口。一般通过ApplicationEventPublisherAware接口注入spring上下文进行发布。因为spring上下文实现了ConfigurableApplicationContext这个聚合接口,事件都是通过上下文进行发布,或者直接使用@Resource自动注入ApplicationEventPublisher的实现类,实际上注入的也是spring的上下文。
  • ApplicacationEventMulticaster: 监听器的注册和和事件发布具体执行者,AbstractApplicationContext抽象类中定义好了事件推送的逻辑,这里是事件运转的核心。
1
2
3
4
5
整个事件的驱动链路如下:
ApplicationEventPublisher => ApplicationEventMulticaster => ApplicationListener => ApplicationEvent
事件发布后,通过Multicaster广播给相关的监听器,然后监听器通过 onApplicationEvent() 方法执行事件自定义逻辑

ApplicationEventMulticaster 会被注入到上下文中,上下文refresh中会执行`initApplicationEventMulticaster()`,其中若我们有自定义的SimpleApplicationEventMulticaster,则会优先使用我们自定义的,比如我们可以设置线程池,让事件处理时走异步操作。
  • @EventListener:通过bean方法上的注解动态生成listener。
1
2
3
4
5
上下文refresh流程中:
registerListeners() 注入所有实现了ApplicationListener接口的类

finishBeanFactoryInitialization() => beanFactory.preInstantiateSingletons() => smartSingleton.afterSingletonsInstantiated() => EventListenerMethodProcessor.afterSingletonsInstantiated()
这个流程最后触发EventListenerMethodProcessor,给所有bean进行后置处理,扫描@EventListener注解,根据注解修饰的方法生成listener