目录
基本问题
- 配置文件加载的时机
- 启动类添加到容器中的时机
- 其他的bean添加到容器中的时机
- tomcat的启动时机
- 加在启动类上的注解生效的时机
- mapper bean生成的时机
- Controller与Tomcat关联的时机
拓展问题
- 如果有多个Configuration类是怎么处理的
基本问题解答
1. Spring Boot将调用它的启动类显示的load到容器里
2. prepareContext方法中由beanFactory中的ConfigurationClassPostProcessor对容器中的bean做处理,此时容器中仅有一些预先注册的处理器以及启动类
3. 接下来refreshContext方法中ConfigurationClassParse会对容器中的Configuration做处理,启动类上因为有Configuration注解而被当做Configuration处理,parse的逻辑是读取Configuration上的ComponentScans和ComponentScan注解,拿到注解中配置的basePackages,如果basePackages为空,那就用启动类的文件夹路径作为basePackages,然后扫描该路径下的所有Component(会扫描所有文件,过滤掉不是Component的,所以basePackages配置成controller的路径应该会更快),此时,被直接扫描到的bean就注册到容器中了,但这时候bean之间的依赖仍然没有遍历
4. @EnableAutoConfiguration注解中有@Import(AutoConfigurationImportSelector.class),在parse完Configuration后立刻调用processDeferredImportSelectors处理Selector,最终会调到AutoConfigurationImportSelector中的selectImports方法,这也是一个扩展点,在该方法中会读取classpath下所有的META-INF/spring-autoconfigure-metadata.properties,该文件中配置了许多Configuration,这些Configuration都会处理并生效,内嵌的Tomcat的Confguration也是从这个配置加载的(org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration),从这个Configuration中会注册一个Tomcat的Factory到容器中,随后在context执行onRefresh时会显示创建webServer,里面的逻辑则是从容器中拿到这个factory,创建出tomcat
5. parse完并处理完ImportSelector后会由ConfigurationClassBeanDefinitionReader对之前所有加载的Configurations执行loadBeanDefinitions,这个方法主要是注册Configuration相关的bean,这些bean有通过注解Import Configuration导入的,有注解ImportBeanDefinitionRegistrar导入的。举个例子,@EnableFeignClients注解里面是@Import(FeignClientsRegistrar.class),这时候就会调用FeignClientsRegistrar这个类的方法来导入feign相关的bean,所以这其实是Spring boot给出来的一个扩展点
拓展问题解答
1. parse完Configuration后就拿到了相关联的bean,随之就会对这些bean做检查,如果该bean是Configuration,则继续递归parse
草稿
Configuration上可以使用条件过滤器
@ConditionalOnClass(HikariDataSource.class)
@ConditionalOnMissingBean(DataSource.class)
@ConditionalOnProperty(name = "spring.datasource.type", havingValue = "com.zaxxer.hikari.HikariDataSource", matchIfMissing = true)
@ConditionalOnClass这个可以在对Configuration处理时最先过滤掉,因为这个只需要判断类存不存在就行了
@ConditionalOnProperty这个也可以比较早的处理掉,在配置文件解析完就可以判断了
@ConditionalOnMissingBean这个得最后才能处理,因为要判断bean是不是存在,必须等所有Configuration类解析完,并把所有相关bean都load到容器中才能判断