SpringBoot启动流程分析

本文详细剖析了SpringBoot的启动流程,从SpringApplicationRunListeners的构造到Environment对象的初始化,再到ApplicationContext的创建和刷新。重点讲解了createApplicationContext、prepareContext、refreshContext等关键步骤,涉及BeanDefinition的注册、BeanFactoryPostProcessors的调用顺序,以及ConfigurationClassPostProcessor的作用。通过本文,读者可以深入了解SpringBoot启动背后的机制。
摘要由CSDN通过智能技术生成

SpringBoot启动流程分析

1.SpringApplicationRunListeners

构造SpringApplicationRunListeners,其中包含多个SpringApplicationRunListener
SpringApplicationRunListener实例化过程:

private SpringApplicationRunListeners getRunListeners(String[] args) {
   
		Class<?>[] types = new Class<?>[] {
    SpringApplication.class, String[].class };
		return new SpringApplicationRunListeners(logger,
				getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args));
	}
	
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
   
		ClassLoader classLoader = getClassLoader();
		// Use names and ensure unique to protect against duplicates
		Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
		List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
		AnnotationAwareOrderComparator.sort(instances);
		return instances;
	}

通过SpringFactoriesLoader获取到spring.factories中定义的SpringApplicationRunListener
默认情况下只有EventPublishingRunListener,会在spring启动的不同阶段发布不同的事件

构造完成后调用listeners.starting(),触发所有listener中的starting方法

2.初始化Environment对象

private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
			ApplicationArguments applicationArguments) {
   
		// Create and configure the environment
		ConfigurableEnvironment environment = getOrCreateEnvironment();
		configureEnvironment(environment, applicationArguments.getSourceArgs());
		ConfigurationPropertySources.attach(environment);
		listeners.environmentPrepared(environment);
		bindToSpringApplication(environment);
		if (!this.isCustomEnvironment) {
   
			environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment,
					deduceEnvironmentClass());
		}
		ConfigurationPropertySources.attach(environment);
		return environment;
	}

getOrCreateEnvironment

private ConfigurableEnvironment getOrCreateEnvironment() {
   
		if (this.environment != null) {
   
			return this.environment;
		}
		switch (this.webApplicationType) {
   
		case SERVLET:
			return new StandardServletEnvironment();
		case REACTIVE:
			return new StandardReactiveWebEnvironment();
		default:
			return new StandardEnvironment();
		}
	}

根据不同的webApplicationType类型创建不同的ConfigurableEnvironment
这里以最常见的SERVLET举例
构造方法内部通过调用customizePropertySources方法对propertySources进行初始化和赋值

protected void customizePropertySources(MutablePropertySources propertySources) {
   
		propertySources.addLast(new StubPropertySource(SERVLET_CONFIG_PROPERTY_SOURCE_NAME));
		propertySources.addLast(new StubPropertySource(SERVLET_CONTEXT_PROPERTY_SOURCE_NAME));
		if (JndiLocatorDelegate.isDefaultJndiEnvironmentAvailable()) {
   
			propertySources.addLast(new JndiPropertySource(JNDI_PROPERTY_SOURCE_NAME));
		}
		super.customizePropertySources(propertySources);
	}


protected void customizePropertySources(MutablePropertySources propertySources) {
   
		propertySources.addLast(
				new PropertiesPropertySource(SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, getSystemProperties()));
		propertySources.addLast(
				new SystemEnvironmentPropertySource(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, getSystemEnvironment()));
	}

方法结束后一共初始化了4个属性

  • servletConfigInitParams
  • servletContextInitParams
  • systemProperties
  • systemEnvironment

configureEnvironment

protected void configureEnvironment(ConfigurableEnvironment environment, String[] args) {
   
		if (this.addConversionService) {
   
			ConversionService conversionService = ApplicationConversionService.getSharedInstance();
			environment.setConversionService((ConfigurableConversionService) conversionService);
		}
		configurePropertySources(environment, args);
		configureProfiles(environment, args);
	}
  • 配置类型转化服务ApplicationConversionService
  • 通过configurePropertySources新增defaultProperties和addCommandLineProperties
  • 配置profile

ConfigurationPropertySources.attach

public static void attach(Environment environment) {
   
		Assert.isInstanceOf(ConfigurableEnvironment.class, environment);
		MutablePropertySources sources = ((ConfigurableEnvironment) environment).getPropertySources();
		PropertySource<?> attached = sources.get(ATTACHED_PROPERTY_SOURCE_NAME);
		if (attached != null && attached.getSource() != sources) {
   
			sources.remove(ATTACHED_PROPERTY_SOURCE_NAME);
			attached = null;
		}
		if (attached == null) {
   
			sources.addFirst(new ConfigurationPropertySourcesPropertySource(ATTACHED_PROPERTY_SOURCE_NAME,
					new SpringConfigurationPropertySources(sources)));
		}
	}

把所有的属性又包了一层,作为configurationProperties

listeners.environmentPrepared(environment);

触发监听器environmentPrepared事件

将 environment中的spring.main开头的属性 绑定到SpringApplication 中的属性值上

protected void bindToSpringApplication(ConfigurableEnvironment environment) {
   
		try {
   
			Binder.get(environment).bind("spring.main", Bindable.ofInstance(this));
		}
		catch (Exception ex) {
   
			throw new IllegalStateException("Cannot bind to SpringApplication", ex);
		}
	}

configureIgnoreBeanInfo(environment);

设置spring.beaninfo.ignore的值,默认为true,保证某些bean不会添加到准备环境中

3 创建applicationContext

3.1 createApplicationContext

根据不同的webApplicationType初始化ApplicationContext
以servlet为例,则是创建出AnnotationConfigServletWebApplicationContext对象
还创建了reader对象、scanner对象和新的environment对象

3.2 prepareContext

初始化applicationContext,将application注册beanDefinition,为refresh做准备

3.2.1 postProcessApplicationContext
protected void postProcessApplicationContext(ConfigurableApplicationContext context) {
   
		if 
Spring Boot是一个开源的Java框架,用于构建独立的、可执行的、生产级的Spring应用程序。它提供了一个快速、简单的方式来开发和部署应用程序。而在Spring Boot的启动过程中,有以下几个主要的步骤: 1. 加载启动类:Spring Boot应用程序的启动类通常是一个带有`@SpringBootApplication`注解的Java类。在应用程序启动时,会通过`main`方法加载这个启动类。 2. 创建Spring Application对象:Spring Boot会创建一个`SpringApplication`对象,用于启动应用程序。`SpringApplication`是Spring Boot框架的核心类,它负责管理整个应用程序的生命周期。 3. 解析配置信息:在启动过程中,`SpringApplication`会解析`application.properties`或`application.yaml`文件中的配置信息,并将其加载到Spring环境中。这些配置信息可以用来配置应用程序的各个方面,如数据库连接、日志级别等。 4. 创建并配置Spring容器:Spring Boot使用Spring容器来管理应用程序中的各个Bean。在启动过程中,`SpringApplication`会根据配置信息创建并配置一个Spring容器,该容器负责加载和管理应用程序中的所有Bean。 5. 执行自定义逻辑:在Spring Boot的启动过程中,可以添加自定义的逻辑。例如,可以通过实现`CommandLineRunner`接口来在应用程序启动后执行一些初始化操作。 6. 启动应用程序:完成上述步骤后,`SpringApplication`会启动应用程序,并通过Servlet容器(如Tomcat、Jetty等)监听端口,开始接收和处理HTTP请求。 总体而言,Spring Boot启动流程是一个通过加载启动类、解析配置信息、创建和配置Spring容器的过程。通过Spring Boot的自动配置和快速启动能力,开发者可以更加方便地构建和部署Spring应用程序。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值