不属于源码阅读,属于debug源码,看启动流程
1 @SpringBootApplication
- 表明是一个注解类
- 指定扫描路径
- 导入两个类
- AutoConfigurationPackages.Registrar.class
- registry.registerBeanDefinition(BEAN, new BasePackagesBeanDefinition(packageNames));
- AutoConfigurationImportSelector.class
- return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
- AutoConfigurationPackages.Registrar.class
先简单说明导入的两个类,一个是创建 BasePackagesBeanDefinition(默认传入启动类的包名,可以在使用@SpringBootApplication的时候指定),并放到beanDefinitionMap(ioc存储beandefinition的)
// 还差个东西
2 org.springframework.boot.SpringApplication#run(java.lang.Class<?>, java.lang.String…)
run方法下去之后到这(分成两个文明东西,一个是构造方法,一个是run方法):
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
return new SpringApplication(primarySources).run(args);
}
2.1 org.springframework.boot.SpringApplication// 构造方法
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
// 保存启动类/配置类
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
// 根据导入的包判断是哪一种中间键(REACTIVE,SERVLET或NONE)
this.webApplicationType = WebApplicationType.deduceFromClasspath();
// 解析spring.factories,取出BootstrapRegistryInitializer,ApplicationContextInitializer和ApplicationListener的实现类,并创建对象
this.bootstrapRegistryInitializers = new ArrayList<>(
getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
// 保存启动类(含有方法 main)
this.mainApplicationClass = deduceMainApplicationClass();
}
2.2 org.springframework.boot.SpringApplication#run(java.lang.String…)
public ConfigurableApplicationContext run(String... args) {
long startTime = System.nanoTime();
DefaultBootstrapContext bootstrapContext = createBootstrapContext();
ConfigurableApplicationContext context = null;
/*
外接设备配置
System.setProperty(
SYSTEM_PROPERTY_JAVA_AWT_HEADLESS,
System.getProperty(
SYSTEM_PROPERTY_JAVA_AWT_HEADLESS,
Boolean.toString(this.headless)));
getProperty传两个参数,如果没有就用后面的默认值
*/
configureHeadlessProperty();
// 获取listeners
SpringApplicationRunListeners listeners = getRunListeners(args);
// 执行所有listener的start方法
listeners.starting(bootstrapContext, this.mainApplicationClass);
try {
// 组装args
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
// 所有系统参数,配置文件参数,命令行参数等都在这里
ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
// 设置 System.setProperty(CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME, ignore.toString())
configureIgnoreBeanInfo(environment);
Banner printedBanner = printBanner(environment);
// 创建spring容器:AnnotationConfigServletWebServerApplicationContext
context = createApplicationContext();
// 感觉就是打日志的
context.setApplicationStartup(this.applicationStartup);
// 设置环境,ConversionService,ApplicationContextInitializer#initialize
// SpringApplicationRunListener#contextPrepared
// org.springframework.boot.DefaultBootstrapContext#close 回调close
// 日志打印激活的环境
// beanFactory.registerSingleton("springApplicationArguments", applicationArguments);// 启动参数的包装
// beanFactory.registerSingleton("springBootBanner", printedBanner);启动项目打印的spring
// 阻止循环引用 ((AbstractAutowireCapableBeanFactory) beanFactory).setAllowCircularReferences(this.allowCircularReferences)
// 是否允许同名beandefinitiong覆盖
// context.addBeanFactoryPostProcessor(new PropertySourceOrderingBeanFactoryPostProcessor(context));
// 配置类/启动类装配成beandefintion 放到容器中
// SpringApplicationRunListener#contextLoaded
prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
// ioc容器启动
refreshContext(context);
// 空实现
afterRefresh(context, applicationArguments);
Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);
}
// ConfigurableApplicationContext, java.time.Duration)
listeners.started(context, timeTakenToStartup);
// ApplicationRunner和CommandLineRunner的run()
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
handleRunFailure(context, ex, listeners);
throw new IllegalStateException(ex);
}
try {
Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
// SpringApplicationRunListener#ready
listeners.ready(context, timeTakenToReady);
}
catch (Throwable ex) {
handleRunFailure(context, ex, null);
throw new IllegalStateException(ex);
}
return context;
}
3 相关重点说明
一句话叫做抛开世事不谈,你就没有错吗,
我这抛开所有扩展功能(监听等)和spring,基础功能(import注解的解析等),只关注:
- spring.factories中的org.springframework.boot.autoconfigure.EnableAutoConfiguration什么时候读
- 什么时候创建这个beandefinition
- 什么时候创建这个bean到单例池
3.1 读取spring.factories中的org.springframework.boot.autoconfigure.EnableAutoConfiguration什么时候读
refresh:564, AbstractApplicationContext (org.springframework.context.support)
invokeBeanFactoryPostProcessors:748, AbstractApplicationContext (org.springframework.context.support)
invokeBeanFactoryPostProcessors:112, PostProcessorRegistrationDelegate (org.springframework.context.support)
invokeBeanDefinitionRegistryPostProcessors:311, PostProcessorRegistrationDelegate (org.springframework.context.support)
postProcessBeanDefinitionRegistry:247, ConfigurationClassPostProcessor (org.springframework.context.annotation)
/******************* 以上是ioc容器执行 BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry ConfigurationClassPostProcessor是我们实现需要功能的实现类 *******************/
// 然后是找到 我们在启动类上import的 AutoConfigurationImportSelector.class,执行 process
processConfigBeanDefinitions:331, ConfigurationClassPostProcessor (org.springframework.context.annotation)
parse:192, ConfigurationClassParser (org.springframework.context.annotation)
process:780, ConfigurationClassParser$DeferredImportSelectorHandler (org.springframework.context.annotation)
processGroupImports:809, ConfigurationClassParser$DeferredImportSelectorGroupingHandler (org.springframework.context.annotation)
getImports:879, ConfigurationClassParser$DeferredImportSelectorGrouping (org.springframework.context.annotation)
process:441, AutoConfigurationImportSelector$AutoConfigurationGroup (org.springframework.boot.autoconfigure)
getAutoConfigurationEntry:125, AutoConfigurationImportSelector (org.springframework.boot.autoconfigure)
3.1.1 重要代码块
// 那多配置文件中的所有 EnableAutoConfiguration 配置
// org.springframework.boot.autoconfigure.AutoConfigurationImportSelector#getCandidateConfigurations
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
List<String> configurations = new ArrayList<>(
SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader()));
ImportCandidates.load(AutoConfiguration.class, getBeanClassLoader()).forEach(configurations::add);
Assert.notEmpty(configurations,
"No auto configuration classes found in META-INF/spring.factories nor in META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports. If you "
+ "are using a custom packaging, make sure that file is correct.");
return configurations;
}
// 上面的方法是这个方法的 List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
// 拿到返回值,下面还有操作
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
AnnotationAttributes attributes = getAttributes(annotationMetadata);
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
configurations = removeDuplicates(configurations);
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
/*
根据@Conditiong注解等,筛选
*/
configurations = getConfigurationClassFilter().filter(configurations);
// 找到对应的listen,执行
fireAutoConfigurationImportEvents(configurations, exclusions);
// 组装成 new AutoConfigurationEntry(configurations, exclusions),并保存到 autoConfigurationEntries中
return new AutoConfigurationEntry(configurations, exclusions);
}
3.2 将配置的类组装成beandefinition
// 没看懂,周末看吧
refresh:564, AbstractApplicationContext (org.springframework.context.support)
invokeBeanFactoryPostProcessors:748, AbstractApplicationContext (org.springframework.context.support)
invokeBeanFactoryPostProcessors:112, PostProcessorRegistrationDelegate (org.springframework.context.support)
invokeBeanDefinitionRegistryPostProcessors:311, PostProcessorRegistrationDelegate (org.springframework.context.support)
postProcessBeanDefinitionRegistry:247, ConfigurationClassPostProcessor (org.springframework.context.annotation)
processConfigBeanDefinitions:343, ConfigurationClassPostProcessor (org.springframework.context.annotation)
/******** 之前的功能是在读取spring.factories 中的内容,并解析 @Bean会接写成 beanMethod *****/
// 举例
/*
// 配置在 spring.factories 中的
@Configuration
@EnableConfigurationProperties({CsiiProperty.class})
public class CsiiConfig {
@Bean
@ConditionalOnMissingBean({CsiiService.class})
public CsiiService csiiService() {
return new CsiiService();
}
}
*/
loadBeanDefinitions:129, ConfigurationClassBeanDefinitionReader (org.springframework.context.annotation)
loadBeanDefinitionsForConfigurationClass:153, ConfigurationClassBeanDefinitionReader (org.springframework.context.annotation)
loadBeanDefinitionsForBeanMethod:238, ConfigurationClassBeanDefinitionReader (org.springframework.context.annotation)
3.3 什么时候创建这个bean到单例池
/*
UserController中依赖UserService
UserService 是在 配置文件 UserConfig 中通过@Bean注解 惊醒控制反转的
UserConfig是配置在spring.factories中的,代码结构
/******需要自己写的代码开始****************/
@Controller
public UserController {
@Resource
private UserService userService;
}
/******需要自己写的代码结束***************/
/******引入starter包开始***************/
public class UserService {}
@Configuration
public class UserConfig {
@Bean
public UserService userService(){
return new UserService();
}
}
// spring.factories文件
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
包名.UserConfig
/******引入starter包结束***************/
*/
简单描述:
1.创建Usercontroller的时候,由于依赖注入要创建UserService
2.UserService是由@Bean交给spring的,在解析这个注解的时候,
3.就会将配置类的name放到UserService的beandefinition中的 factoryBeanName 字段中,现在取出这个字段,到spring容器中取这个配置bean(创建)
1.创建Usercontroller的时候,由于依赖注入要创建UserService
refresh:583, AbstractApplicationContext (org.springframework.context.support)
finishBeanFactoryInitialization:920, AbstractApplicationContext (org.springframework.context.support)
preInstantiateSingletons:955, DefaultListableBeanFactory (org.springframework.beans.factory.support)
getBean:208, AbstractBeanFactory (org.springframework.beans.factory.support)
doGetBean:333, AbstractBeanFactory (org.springframework.beans.factory.support)
getSingleton:234, DefaultSingletonBeanRegistry (org.springframework.beans.factory.support)
getObject:-1, 1677568775 (org.springframework.beans.factory.support.AbstractBeanFactory$$Lambda$209)
lambda$doGetBean$0:335, AbstractBeanFactory (org.springframework.beans.factory.support)
createBean:542, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
doCreateBean:619, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
populateBean:1431, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
2.UserService是由@Bean交给spring的,在解析这个注解的时候,
postProcessProperties:329, CommonAnnotationBeanPostProcessor (org.springframework.context.annotation)
inject:119, InjectionMetadata (org.springframework.beans.factory.annotation)
inject:228, InjectionMetadata$InjectedElement (org.springframework.beans.factory.annotation)
getResourceToInject:673, CommonAnnotationBeanPostProcessor$ResourceElement (org.springframework.context.annotation)
getResource:520, CommonAnnotationBeanPostProcessor (org.springframework.context.annotation)
autowireResource:550, CommonAnnotationBeanPostProcessor (org.springframework.context.annotation)
resolveBeanByName:479, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
getBean:213, AbstractBeanFactory (org.springframework.beans.factory.support)
doGetBean:333, AbstractBeanFactory (org.springframework.beans.factory.support)
getSingleton:234, DefaultSingletonBeanRegistry (org.springframework.beans.factory.support)
getObject:-1, 1677568775 (org.springframework.beans.factory.support.AbstractBeanFactory$$Lambda$209)
lambda$doGetBean$0:335, AbstractBeanFactory (org.springframework.beans.factory.support)
createBean:542, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
doCreateBean:582, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
createBeanInstance:1195, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
instantiateUsingFactoryMethod:1352, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
3.就会将配置类的name放到UserService的beandefinition中的 factoryBeanName 字段中,现在取出这个字段,到spring容器中取这个配置bean
instantiateUsingFactoryMethod:410, ConstructorResolver (org.springframework.beans.factory.support)
getBean:208, AbstractBeanFactory (org.springframework.beans.factory.support)