Spring
Spring主要加载链路分析
包扫描
1 | <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
3ConfigurationClassUtils
#checkConfigurationClassCandidate()
#isConfigurationCandidate()缓存到元数据读取工厂 metadataReaderFactory
processConfigurationClass() 递归处理
配置类处理逻辑
ConfigurationClassParser #processConfigurationClass
- 获取配置类缓存 configurationClasses
- 已存在缓存,配置类与 @Imported 有关,则执行完相关逻辑后直接return
- 已存在缓存,配置类与 @Imported 无关,讲配置类从缓存中去除,继续执行重新加载(具体处理原因源码中有注释)
- 递归处理配置类及其父类 #doProcessConfigurationClass 有父类则通过方法返回值赋值,递归处理
- 配置类放入缓存 configurationClasses
- 获取配置类缓存 configurationClasses
ConfigurationClassParser #doProcessConfigurationClass
配置类是否有 @Component ,有则先递归处理内部类 #processMemberClasses
- TODO
处理 @PropertySource
处理 @ComponentScan 包扫描
ComponentScanAnnotationParser #parse 包扫描解析,根据ComponentScan注解配置对扫描器进行配置,然后执行扫描 scanner.doScan(…)
ClassPathBeanDefinitionScanner #doscan => #findCandidateComponents 通过类加载器以及配置路径,从编译后文件中获取。
#isCandidateComponent(MetadataReader metadataReader) 获取可自动装配类,包括 @Component,具体看方法实现,其中includeFilters包含了@Component
for 处理包扫描结果集
转换成BeanDefinition
校验BeanDefinition,主要关注以下方法,一般自动装配类都会通过校验
1
2
3ConfigurationClassUtils
#checkConfigurationClassCandidate()
#isConfigurationCandidate()通过校验后解析相应BeanDefinition #parse(String className, String beanName)
缓存到元数据读取工厂 metadataReaderFactory
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 | 整个事件的驱动链路如下: |
- @EventListener:通过bean方法上的注解动态生成listener。
1 | 上下文refresh流程中: |