Spring-Boot启动流程

本文详细解析了Spring Boot启动过程中的关键步骤,包括创建SpringApplication对象、启动run方法、refresh容器、执行BeanFactoryPostProcessor、注册BeanPostProcessors、初始化事件广播者、注册事件监听者及实例化非懒加载单例Bean。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、创建SpringApplication对象

首先new 了一个SpringApplication对象,参数source是是我们的启动类。

	private void initialize(Object[] sources) {
		if (sources != null && sources.length > 0) {
			this.sources.addAll(Arrays.asList(sources));
		}
		// 1. 根据classpath里面是否存在某个特征类来决定webEnvironment参数
		this.webEnvironment = deduceWebEnvironment();
		// 2. 加载所有实现了ApplicationContextInitializer接口的对象
		setInitializers((Collection) getSpringFactoriesInstances(
				ApplicationContextInitializer.class));
		//3. 加载所有实现了ApplicationListener接口的对象
		setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
		// 4. 推断并设置main方法的定义类。
		this.mainApplicationClass = deduceMainApplicationClass();
	}

  1. 根据classpath里面是否存在某个特征类来决定webEnvironment参数,否应该创建一个为Web应用使用的ApplicationContext类型。
  2. 重点在于getSpringFactoriesInstances,获取指定类型的已经加载的对象,这里不是走的容器,而是从spring.factories文件中读取对应的类和路径。将所有实现了ApplicationContextInitializer接口的对象设置到this.initializers。这些对象可以修改applicationContext,这里只是设置,还没有调用,到prepareContext方法里会调用。例如Apollo配置就是在这里获取远程配置然后设置到context中的environment属性的PropertySources中去。
  3. 加载所有ApplicationListener,加载方式也是从spring.factories文件中获取
public interface ApplicationContextInitializer<C extends ConfigurableApplicationContext> {

	/**
	 * Initialize the given application context.
	 * @param applicationContext the application to configure
	 */
	void initialize(C applicationContext);

}

3.将所有实现了ApplicationListener接口的listner设置到this.listeners.

public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {

   /**
    * Handle an application event.
    * @param event the event to respond to
    */
   void onApplicationEvent(E event);

}

二、启动,run

ConfigurableApplicationContext context = null;
FailureAnalyzers analyzers = null;
configureHeadlessProperty();
// 1. 获取所有实现了SpringApplicationRunListener接口的对象,区别于ApplicationListener
SpringApplicationRunListeners listeners = getRunListeners(args);
// 执行RunListener的starting方法
listeners.starting();
try {
	ApplicationArguments applicationArguments = new DefaultApplicationArguments(
			args);
	// 2.  创建并配置当前Spring Boot应用将要使用的Environment(包括配置要使用的PropertySource以及Profile)。
	ConfigurableEnvironment environment = prepareEnvironment(listeners,
			applicationArguments);
	Banner printedBanner = printBanner(environment);
	// 3. 根据applicationContextClass类型,默认创建AnnotationConfigApplicationContext,同时设置了reader和scanner
	context = createApplicationContext();
	analyzers = new FailureAnalyzers(context);
	// 4. 为conext设置环境属性,是否使用自定义的BeanNameGenerator,决定是否使用自定义的ResourceLoader,同时还加载了一些默认加载的bean定义
	// 这里面还会调用applyInitializers,来调用前面创建的ApplicationContextInitializer
	prepareContext(context, environment, listeners, applicationArguments,
			printedBanner);
	// 5. Spring boot扩展关键点,更新context
	refreshContext(context);
	afterRefresh(context, applicationArguments);
	listeners.finished(context, null);
	stopWatch.stop();
	if (this.logStartupInfo) {
		new StartupInfoLogger(this.mainApplicationClass)
				.logStarted(getApplicationLog(), stopWatch);
	}
	return context;
}
  1. 构造Listeners,这里是SpringApplicationRunListener。
public interface SpringApplicationRunListener {
	void starting();
	void environmentPrepared(ConfigurableEnvironment environment);
	void contextPrepared(ConfigurableApplicationContext context);
	void contextLoaded(ConfigurableApplicationContext context);
	void started(ConfigurableApplicationContext context);
	void running(ConfigurableApplicationContext context);
	void failed(ConfigurableApplicationContext context, Throwable exception);
}
  1. 设置Environment(包括配置要使用的PropertySource以及Profile,一些配置信息
  2. 创建context,实质是AnnotationConfigApplicationContext对象,这里创建了两个关键对象:AnnotatedBeanDefinitionReader,ClassPathBeanDefinitionScanner
  • 3.1 AnnotatedBeanDefinitionReader,适配了一些使用代码对bean进行注册的方法,如registerBean
  • 3.2 ClassPathBeanDefinitionScanner,用于扫描@Component,@Service这种类,注册到容器中。是通过ConfigurationClassPostProcessor中调用的,在之后的refresh操作中。

4.这里主要是加载一些影响到Spring功能的Bean的定义,以及我们的启动类的Bean,这里只是加载了BeanDefinition还没有实例化。同时还调用了前面创建的ApplicationContextInitializer对象

  • 4.1 ConfigurationClassPostProcessor, 实现了BeanFactoryPostProcessor,用于处理@Configuration
  • 4.2 DefaultEventListenerFactory,处理@EventListener
  • 4.3 EventListenerMethodProcessor,实现了BeanFactoryPostProcessor,也是用于处理处理@EventListener
  • 4.4 AutowiredAnnotationBeanPostProcessor,实现了BeanFactoryPostProcessor,用于处理@Autowired,@Value
  • 4.5 CommonAnnotationBeanPostProcessor, 处理@PostConstruct,@PreDestroy,@Resource
  • 4.6 MyApplication
  1. 关键点,Spring扩展点,Spring-boot关键

三、refresh修改容器

AbstractApplicationContext类中的refresh方法关键代码


// Prepare this context for refreshing.
prepareRefresh();

// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

// Prepare the bean factory for use in this context.
1.实例化了一些bean,如environment,systemEnvironment,systemProperties
prepareBeanFactory(beanFactory);
			
// 2. 提供给子类进行扩展,对beanFactory进行处理
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);

// 3. 核心代码,实例化并执行所有注册的BeanFactoryPostProcessor
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);

// Register bean processors that intercept bean creation.
// 4. 注册BeanPostProcessors
registerBeanPostProcessors(beanFactory);

// Initialize message source for this context.
initMessageSource();

// Initialize event multicaster for this context.
initApplicationEventMulticaster();

// Initialize other special beans in specific context subclasses.
onRefresh();

// Check for listener beans and register them.
registerListeners();

// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);

// Last step: publish corresponding event.
finishRefresh();

四、refresh之:执行BeanFactoryPostProcessor来扩展功能

4.1 执行BeanDefinitionRegistryPostProcessors

1.执行实现了PriorityOrdered接口的类
这里会执行系统自带的ConfigurationClassPostProcessor以及实现了PriorityOrdered
在PostProcessorRegistrationDelegate类中的invokeBeanFactoryPostProcessors方法代码片段

// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
String[] postProcessorNames =
		beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
	if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
	    // 这里调用了beanFactory.getBean方法
		currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
		processedBeans.add(ppName);
	}
}
//排序
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
// 调用
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);

2.执行实现了BeanDefinitionRegistryPostProcessor和Ordered的类

3.执行其他BeanDefinitionRegistryPostProcessor

4.2 执行BeanFactoryPostProcessors类

1.执行实现了PriorityOrdered接口的类

2.执行实现了Ordered的类

3.执行所有其他BeanFactoryPostProcessors类

4.3 扫描Bean并注册的流程

  1. 使用ConfigurationClassPostProcessor来构造ConfigurationClassParser。
  2. 处理@ComponentScan注解,扫描路径中的包获得BeanDefinition列表。然后遍历该列表的所有BeanDefinition,递归解析该BeanDefinition,回到第二步。
  3. 处理@Import注解。
  4. 处理所有的@Bean注解的方法。
  5. 如果有父类,处理父类。

ConfigurationClassPostProcessor类中主要使用ConfigurationClassParser来解析各种用来引入Bean的注解配置。
这里构造函数有几个关键参数,

  • this.resourceLoader就是前面提到的AnnotationConfigApplicationContext,这个ApplicationContext有两个关键属性,reader和scanner,scanner用来从package路径扫描类,解析各种注解。reader用来加载特定类型的Bean。
  • registry就是BeanFactory
  • this.componentScanBeanNameGenerator用来生成Bean名称的对象
// Parse each @Configuration class
ConfigurationClassParser parser = new ConfigurationClassParser(
	this.metadataReaderFactory, this.problemReporter, this.environment,
	this.resourceLoader, this.componentScanBeanNameGenerator, registry);

所以在实例化我们通常的@Service等Bean之前,Spring-boot先实例化了所有的BeanFactoryProcessor,然后调用处理方法,主要使用ConfigurationClassPostProcessor类来作为扫描的入口,进行一系列的递归扫描操作。

五、refresh之:注册BeanPostProcessors来扩展功能

这一步只是注册了所有的BeanPostProcessor,真正调用是在实例化Bean的时候调用的。注册顺序同样是先注册PriorityOrdered,再到Ordered,再到没有顺序的,最后再注册所有实现了MergedBeanDefinitionPostProcessor接口的,这种被称为internalPostProcessors。注意,一个相同的对象,后面注册的会覆盖前面的位置。
实现代码在PostProcessorRegistrationDelegate类的registerBeanPostProcessors方法中。
覆盖逻辑在AbstractBeanFactory中实现。

@Override
public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
	Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null");
	// Remove from old position, if any
	this.beanPostProcessors.remove(beanPostProcessor);
	// Track whether it is instantiation/destruction aware
	if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {
		this.hasInstantiationAwareBeanPostProcessors = true;
	}
	if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) {
		this.hasDestructionAwareBeanPostProcessors = true;
	}
	// Add to end of list
	this.beanPostProcessors.add(beanPostProcessor);
}

这里提一点,对于那种XXXProcessor类,都是一个外部的处理者,在XXX创建过程中进行一定的处理。还有一个Aware接口,XXXAware是由XXX对象自己来实现的,实现后它就能感知到自己生命周期中的某些事件。比如BeanFactoryAware,BeanNameAware等待。总而言之就是调自己的方法来改变自己,而不是改变别人。

private void invokeAwareMethods(final String beanName, final Object bean) {
		if (bean instanceof Aware) {
			if (bean instanceof BeanNameAware) {
				((BeanNameAware) bean).setBeanName(beanName);
			}
			if (bean instanceof BeanClassLoaderAware) {
				ClassLoader bcl = getBeanClassLoader();
				if (bcl != null) {
					((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
				}
			}
			if (bean instanceof BeanFactoryAware) {
				((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
			}
		}
	}

六、refresh之:初始化事件广播者(applicationEventMulticaster)

代码很简单,就是如果容器中有对应的名为applicationEventMulticaster的Bean,则实例化对应的Bean,否则就new一个SimpleApplicationEventMulticaster。

protected void initApplicationEventMulticaster() {
	ConfigurableListableBeanFactory beanFactory = getBeanFactory();
	if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
		this.applicationEventMulticaster =
				beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
		if (logger.isTraceEnabled()) {
			logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
		}
	}
	else {
		this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
		beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
		if (logger.isTraceEnabled()) {
			logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " +
					"[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");
		}
	}
}

事件广播使用了一个标准的观察者模式,系统在初始化的时候会在context中注册一个applicationListeners,如果系统有需要广播的情况下,会发送一个applicationEvent事件,注册的listener会根据自己关心的类型进行接收和解析。
主要对象有三个:

  1. ApplicationEvent事件抽象类,抽象了一个事件,仅包含了时间戳和发送消息的对象。
  2. ApplicationListener监听者接口,只有一个方法 void onApplicationEvent(E event);
  3. ApplicationEventMulticaster广播者,负责接收事件,注册ApplicationListener,然后将对应的事件ApplicationEvent分发给对应的监听者ApplicationListener。

七、refresh之: 注册事件监听者

这里首先将我们第一节实例化的ApplicationListener都注册到第六节创建的applicationEventMulticaster对象中,然后将实现了ApplicationListener接口的Bean的名称注册进去,这里没有进行实例化。然后执行了一个广播操作。

protected void registerListeners() {
	// Register statically specified listeners first.
	// 将第一节已经实例化的Listner注册
	for (ApplicationListener<?> listener : getApplicationListeners()) {
		getApplicationEventMulticaster().addApplicationListener(listener);
	}

	// Do not initialize FactoryBeans here: We need to leave all regular beans
	// uninitialized to let post-processors apply to them!
	String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
	// 将容器中实现了ApplicationListener接口的Bean的Bean名称加入
	for (String listenerBeanName : listenerBeanNames) {
		getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
	}

	// Publish early application events now that we finally have a multicaster...
	Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
	this.earlyApplicationEvents = null;
	if (earlyEventsToProcess != null) {
		for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
			getApplicationEventMulticaster().multicastEvent(earlyEvent);
		}
	}
}

八、 refresh之: 实例化所有非懒加载的单例Bean


	@Override
	public void preInstantiateSingletons() throws BeansException {
		if (logger.isTraceEnabled()) {
			logger.trace("Pre-instantiating singletons in " + this);
		}

		// Iterate over a copy to allow for init methods which in turn register new bean definitions.
		// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
		List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

		// Trigger initialization of all non-lazy singleton beans...
		for (String beanName : beanNames) {
			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
				if (isFactoryBean(beanName)) {
					Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
					if (bean instanceof FactoryBean) {
						final FactoryBean<?> factory = (FactoryBean<?>) bean;
						boolean isEagerInit;
						if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
							isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
											((SmartFactoryBean<?>) factory)::isEagerInit,
									getAccessControlContext());
						}
						else {
							isEagerInit = (factory instanceof SmartFactoryBean &&
									((SmartFactoryBean<?>) factory).isEagerInit());
						}
						if (isEagerInit) {
							getBean(beanName);
						}
					}
				}
				else {
					getBean(beanName);
				}
			}
		}

		// Trigger post-initialization callback for all applicable beans...
		for (String beanName : beanNames) {
			Object singletonInstance = getSingleton(beanName);
			if (singletonInstance instanceof SmartInitializingSingleton) {
				final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
				if (System.getSecurityManager() != null) {
					AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
						smartSingleton.afterSingletonsInstantiated();
						return null;
					}, getAccessControlContext());
				}
				else {
					smartSingleton.afterSingletonsInstantiated();
				}
			}
		}
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值