springboot完整启动流程源码(一)

spring启动流程首先从SpringApplication.run(StartWorkApplication.class, args);这一行代码进入。run方法进入首先会创建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));
		this.webApplicationType = WebApplicationType.deduceFromClasspath();
		this.bootstrapRegistryInitializers = getBootstrapRegistryInitializersFromSpringFactories();
		//创建类型为ApplicationContextInitializer的对象
		setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
		//创建类型为ApplicationListener的对象
		setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
		this.mainApplicationClass = deduceMainApplicationClass();
	}

上面的getSpringFactoriesInstances方法最终会调用loadSpringFactories。
这个方法会读取每一个jar下面的META-INF/spring.factories文件,得到所有的配置类,并返回一个map。接下来获取指定类型的bean创建对象加载到内存。

	private static Map<String, List<String>> loadSpringFactories(ClassLoader classLoader) {
		Map<String, List<String>> result = cache.get(classLoader);
		if (result != null) {
			return result;
		}

		result = new HashMap<>();
		try {
		//从META-INF/spring.factories读取配置类
			Enumeration<URL> urls = classLoader.getResources(FACTORIES_RESOURCE_LOCATION);
			while (urls.hasMoreElements()) {
				URL url = urls.nextElement();
				UrlResource resource = new UrlResource(url);
				Properties properties = PropertiesLoaderUtils.loadProperties(resource);
				for (Map.Entry<?, ?> entry : properties.entrySet()) {
					String factoryTypeName = ((String) entry.getKey()).trim();
					String[] factoryImplementationNames =
							StringUtils.commaDelimitedListToStringArray((String) entry.getValue());
					for (String factoryImplementationName : factoryImplementationNames) {
						result.computeIfAbsent(factoryTypeName, key -> new ArrayList<>())
								.add(factoryImplementationName.trim());
					}
				}
			}

			// Replace all lists with unmodifiable lists containing unique elements
			result.replaceAll((factoryType, implementations) -> implementations.stream().distinct()
					.collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList)));
			cache.put(classLoader, result);
		}
		catch (IOException ex) {
			throw new IllegalArgumentException("Unable to load factories from location [" +
					FACTORIES_RESOURCE_LOCATION + "]", ex);
		}
		return result;
	}

创建完SpringApplication对象后就会调用他的run方法。其中主要的方法是prepareContext和refreshContext。如下:

	public ConfigurableApplicationContext run(String... args) {
		StopWatch stopWatch = new StopWatch();
		stopWatch.start();
		DefaultBootstrapContext bootstrapContext = createBootstrapContext();
		ConfigurableApplicationContext context = null;
		configureHeadlessProperty();
		SpringApplicationRunListeners listeners = getRunListeners(args);
		listeners.starting(bootstrapContext, this.mainApplicationClass);
		try {
			ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
			ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
			configureIgnoreBeanInfo(environment);
			Banner printedBanner = printBanner(environment);
			context = createApplicationContext();
			context.setApplicationStartup(this.applicationStartup);
			prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
			refreshContext(context);
			afterRefresh(context, applicationArguments);
			stopWatch.stop();
			if (this.logStartupInfo) {
				new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
			}
			listeners.started(context);
			callRunners(context, applicationArguments);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, listeners);
			throw new IllegalStateException(ex);
		}

		try {
			listeners.running(context);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, null);
			throw new IllegalStateException(ex);
		}
		return context;
	}

(一)prepareContext方法
prepareContext方法主要做一些预处理的工作,环境信息配置以及预处理一些后置处理器和springApplication启动类。调用链如下:
prepareContext*>>BeanDefinitionLoader#load>>AnnotatedBeanDefinitionReader#register>>GenericApplicationContext#registerBeanDefinition>>*DefaultListableBeanFactory#registerBeanDefinition。可以看到最终调用DefaultListableBeanFactory的registerBeanDefinition方法。这个方法会将项目启动类springApplication的beanDefinition缓存到beanDefinitionMap。
在这里插入图片描述
(二)refreshContext方法
refreshContext调用AbstractApplicationContext#refresh方法。里面的主要逻辑如下:

				// Allows post-processing of the bean factory in context subclasses.		
				//beanFactory扩展点
				postProcessBeanFactory(beanFactory);

				// Invoke factory processors registered as beans in the context.
				//1)执行BeanFactoryPostProcessors
				invokeBeanFactoryPostProcessors(beanFactory);

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

				// Initialize message source for this context.
				//初始化消息  。。。暂时忽略
				initMessageSource();

				// Initialize event multicaster for this context.
				//3)初始化multicaster
				initApplicationEventMulticaster();

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

				// Check for listener beans and register them.
				//4)注册listener 
				registerListeners();
				
				// Instantiate all remaining (non-lazy-init) singletons.
				//5)预先创建非懒加载的单例bean
				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish corresponding event.
				//6)执行LifecycleProcessor的onRefresh方法以及发布ContextRefreshedEvent事件
				finishRefresh();

1)invokeBeanFactoryPostProcessors
invokeBeanFactoryPostProcessors主要是执行BeanFactory的后置处理器。先执行实现了BeanDefinitionRegistryPostProcessor接口的Processor,再执行实现BeanFactoryPostProcessor接口的Processor,实现PriorityOrdered接口的Processor优先于实现Ordered执行。其中ConfigurationClassPostProcessor这个后置处理器实现了BeanDefinitionRegistryPostProcessor和PriorityOrdered接口,会被第一个执行。 ConfigurationClassPostProcessor会处理@ComponentScan,@Import等注解。关于这个类具体的解析逻辑在这篇文章[springboot BeanFactoryPostProcesser之ConfigurationClassPostProcessor]。(https://blog.csdn.net/weixin_38965431/article/details/123595745)

2)registerBeanPostProcessors
registerBeanPostProcessors作用是注册Bean的后置处理器。主要逻辑如下:先注册实现了PriorityOrdered接口的PostProcessor,再注册实现了Ordered接口的BeanPostProcessor,最后再注册剩余的BeanPostProcessor。他的注册逻辑是通过AbstractBeanFactory#doGetBean获取到BeanPostProcessor实例然后缓存到beanPostProcessors集合中。doGetBean创建bean对象的逻辑放到后续篇章。

	public static void registerBeanPostProcessors(
			ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
			//获取BeanPostProcessor类型的beanName
		String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

		//根据优先级不同对这些BeanPostProcessor做不同的划分
		List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
		List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
		List<String> orderedPostProcessorNames = new ArrayList<>();
		List<String> nonOrderedPostProcessorNames = new ArrayList<>();
		for (String ppName : postProcessorNames) {
			if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
			   //创建bean实例,注入到IOC容器
				BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
				priorityOrderedPostProcessors.add(pp);
				if (pp instanceof MergedBeanDefinitionPostProcessor) {
					internalPostProcessors.add(pp);
				}
			}
			else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
				orderedPostProcessorNames.add(ppName);
			}
			else {
				nonOrderedPostProcessorNames.add(ppName);
			}
		}

		// First, register the BeanPostProcessors that implement PriorityOrdered.
		//排序  按照PriorityOrdered值从小到大的顺序
		sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
		//优先注册实现了PriorityOrdered接口的BeanPostProcessor
		registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

		// Next, register the BeanPostProcessors that implement Ordered.
		//再注册实现了Ordered接口的BeanPostProcessor
		List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
		for (String ppName : orderedPostProcessorNames) {
			BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
			orderedPostProcessors.add(pp);
			if (pp instanceof MergedBeanDefinitionPostProcessor) {
				internalPostProcessors.add(pp);
			}
		}
		sortPostProcessors(orderedPostProcessors, beanFactory);
		registerBeanPostProcessors(beanFactory, orderedPostProcessors);
	}

3)initApplicationEventMulticaster
initApplicationEventMulticaster方法主要是注册了一个事件监听广播器SimpleApplicationEventMulticaster。
4)registerListeners
registerListeners的作用是注册事件监听器
5)finishBeanFactoryInitialization
finishBeanFactoryInitialization的作用是提前创建非懒加载的单例Bean。他调用了DefaultListableBeanFactory#preInstantiateSingletons这个方法,内部通过doGetBean创建Bean注入Ioc容器。具体实现如下:

	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...
		//加载所有非懒加载的单例bean
		for (String beanName : beanNames) {
			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
			//非抽象的非懒加载的单例bean
			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
				//处理factorybean
				if (isFactoryBean(beanName)) {
					Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
					if (bean instanceof FactoryBean) {
						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 {
					//处理非factorybean
					getBean(beanName);
				}
			}
		}

		// Trigger post-initialization callback for all applicable beans...
		//如果bean实现了SmartInitializingSingleton,调用afterSingletonsInstantiated进行初始化
		for (String beanName : beanNames) {
			Object singletonInstance = getSingleton(beanName);
			if (singletonInstance instanceof SmartInitializingSingleton) {
				StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize")
						.tag("beanName", beanName);
				SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
				if (System.getSecurityManager() != null) {
					AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
						smartSingleton.afterSingletonsInstantiated();
						return null;
					}, getAccessControlContext());
				}
				else {
					smartSingleton.afterSingletonsInstantiated();
				}
				smartInitialize.end();
			}
		}
	}

6)finishRefresh
finishRefresh主要作用是执行LifecycleProcessor的onRefresh方法以及发布ContextRefreshedEvent事件。发布事件监听器的逻辑也放在后续篇章。

总结:spring启动流程其实主要是refreshContext方法里面的1,2,5步。第一步主要是执行BeanFactoryPostProcessors其中就包括解析各种注解类然后生成BeanDefination描述性信息缓存到BeanDefinationMap。第二步是优先创建各种BeanPostProcessor后置处理器,注册到spring容器,然后在后续创建bean时候会执行这些后置处理器。第五步主要是创建非懒加载的单例bean,根据BeanDefinationMap里面的信息,通过doGetBean创建。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SpringBoot2的启动流程是通过@SpringBootApplication注解自动化配置来实现的。该注解包含了多个注解的组合,其中包括@ComponentScan、@EnableAutoConfiguration和@Configuration等。通过这些注解,Spring Boot会自动扫描并加载配置类,并根据自动配置规则来配置应用程序。 具体而言,当应用程序启动时,Spring Boot会创建一个Spring应用程序上下文。在创建上下文的过程中,会先加载主配置类(通常是包含main方法的类),然后根据@ComponentScan注解扫描指定包下的所有组件。 接下来,Spring Boot会根据@EnableAutoConfiguration注解自动配置应用程序。这个注解会根据classpath和条件匹配的规则,加载配置类,并将它们注册到应用程序上下文中。这些配置类使用了@Configuration注解,会声明一些Bean,并根据条件来决定是否生效。 最后,Spring Boot会启动应用程序,并执行相应的事件处理器。这些事件处理器可以通过自定义ApplicationListener来实现。在应用程序运行期间,Spring Boot会触发不同的事件,并调用相应的事件处理器。 参考文献: 引用:SpringBoot2 | @SpringBootApplication注解 自动化配置流程源码分析(三) [2] 引用:SpringBoot2 | SpringBoot监听器源码分析 | 自定义ApplicationListener(六) 引用:该系列主要还是Spring的核心源码,不过目前Springboot大行其道,所以就从Springboot开始分析。最新版本是Springboot2.0.4,Spring5,所以新特性本系列后面也会着重分析。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值