springboot启动原理

本文详细分析了SpringBoot应用的启动过程,从@SpringBootApplication注解的处理,到SpringApplication.run()方法的执行,包括构造方法和run方法内部的关键步骤。着重讨论了spring.factories中EnableAutoConfiguration的读取、配置类转换为BeanDefinition以及何时创建Bean到单例池的过程。
摘要由CSDN通过智能技术生成

不属于源码阅读,属于debug源码,看启动流程

1 @SpringBootApplication

  • 表明是一个注解类
  • 指定扫描路径
  • 导入两个类
    • AutoConfigurationPackages.Registrar.class
      • registry.registerBeanDefinition(BEAN, new BasePackagesBeanDefinition(packageNames));
    • AutoConfigurationImportSelector.class
      • return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());

先简单说明导入的两个类,一个是创建 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注解的解析等),只关注:

  1. spring.factories中的org.springframework.boot.autoconfigure.EnableAutoConfiguration什么时候读
  2. 什么时候创建这个beandefinition
  3. 什么时候创建这个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)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值