从Springboot源码分析启动过程

从Springboot源码分析启动过程

这篇博客主要是通过Springboot的源码,分析Springboot项目的启动过程,深入理解spring的工作原理。其次,我对部分源码加上了注解,新手可以稍微看一下,同时我也希望大佬们能指出我理解有误的地方。

一、springboot启动源码解析

public ConfigurableApplicationContext run(String... args) {
	StopWatch stopWatch = new StopWatch();
	stopWatch.start();//项目计时器开始计时
	ConfigurableApplicationContext context = null;
	Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();//异常处理类集合
	configureHeadlessProperty();//设置System全局参数
	SpringApplicationRunListeners listeners = getRunListeners(args);//SpringApplicationRunListener.class创建监视器实例
	listeners.starting();//发起starting事件(event)
	try {
		ApplicationArguments applicationArguments = new DefaultApplicationArguments(
				args);//将启动参数转换成spring能解析的格式,例如:--foo=bar --foo="tom"
		ConfigurableEnvironment environment = prepareEnvironment(listeners,
				applicationArguments);
		configureIgnoreBeanInfo(environment);
		Banner printedBanner = printBanner(environment);
		context = createApplicationContext();//根据webApplicationType的类型创建Context对象实例
		exceptionReporters = getSpringFactoriesInstances(
				SpringBootExceptionReporter.class,
				new Class[] { ConfigurableApplicationContext.class }, context);
		prepareContext(context, environment, listeners, applicationArguments,
				printedBanner);//准备项目运行的环境,加载xml文件中配置的bean
		refreshContext(context);//更新Context 执行用户定义的postProcessBeanFactory操作,注册listener相关的bean,初始化所以剩下的单例类
		afterRefresh(context, applicationArguments);//用户自定义的操作
		stopWatch.stop();//项目计时器结束计时
		if (this.logStartupInfo) {
			new StartupInfoLogger(this.mainApplicationClass)
					.logStarted(getApplicationLog(), stopWatch);//打印日志信息
		}
		listeners.started(context);//发起ApplicationStartedEvent事件
		callRunners(context, applicationArguments);//启动SpringApplication
	}
	catch (Throwable ex) {
		handleRunFailure(context, ex, exceptionReporters, listeners);
		throw new IllegalStateException(ex);
	}

	try {
		listeners.running(context);//发起ApplicationReadyEvent事件
	}
	catch (Throwable ex) {
		handleRunFailure(context, ex, exceptionReporters, null);
		throw new IllegalStateException(ex);
	}
	return context;
}

二、SpringApplication 类部分源码解析

/**
 * 准备项目运行时的环境变量
 * @param listeners 各种监听器
 * @param applicationArguments 参数对象
 * @return
 */
private ConfigurableEnvironment prepareEnvironment(
		SpringApplicationRunListeners listeners,
		ApplicationArguments applicationArguments) {
	// Create and configure the environment
	ConfigurableEnvironment environment = getOrCreateEnvironment();//初始化environment的Properties和configuration
	configureEnvironment(environment, applicationArguments.getSourceArgs());//添加或替换commandLineArgs在environment中的属性值 确保profile被正确配置
	listeners.environmentPrepared(environment);//发起ApplicationEnvironmentPreparedEvent事件
	bindToSpringApplication(environment);
	if (!this.isCustomEnvironment) {
		environment = new EnvironmentConverter(getClassLoader())
				.convertEnvironmentIfNecessary(environment, deduceEnvironmentClass());
	}
	ConfigurationPropertySources.attach(environment);
	return environment;
}

/**
 * 根据项目类型选择具体的环境参数类
 * @return
 */
private Class<? extends StandardEnvironment> deduceEnvironmentClass() {
	switch (this.webApplicationType) {
	case SERVLET:
		return StandardServletEnvironment.class;
	case REACTIVE:
		return StandardReactiveWebEnvironment.class;
	default:
		return StandardEnvironment.class;
	}
}

/**
 * 初始化项目上下文环境,具体的初始化内容看参数命名就清楚了
 * @param context
 * @param environment
 * @param listeners
 * @param applicationArguments
 * @param printedBanner
 */
private void prepareContext(ConfigurableApplicationContext context,
		ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
		ApplicationArguments applicationArguments, Banner printedBanner) {
	context.setEnvironment(environment);
	postProcessApplicationContext(context);
	applyInitializers(context);
	listeners.contextPrepared(context);
	if (this.logStartupInfo) {
		logStartupInfo(context.getParent() == null);
		logStartupProfileInfo(context);
	}
	// Add boot specific singleton beans
	ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
	beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
	if (printedBanner != null) {
		beanFactory.registerSingleton("springBootBanner", printedBanner);
	}
	if (beanFactory instanceof DefaultListableBeanFactory) {
		((DefaultListableBeanFactory) beanFactory)
				.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
	}
	// Load the sources
	Set<Object> sources = getAllSources();
	Assert.notEmpty(sources, "Sources must not be empty");
	load(context, sources.toArray(new Object[0]));
	listeners.contextLoaded(context);
}

/**
 * 从spring的资源目录下加载factory对象的路径名,资源文件是META-INF/spring.factories
 * @param type
 * @param parameterTypes
 * @param args
 * @param <T>
 * @return
 */
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));//从spring的资源目录下加载factory对象的路径名,资源文件是META-INF/spring.factories
	List<T> instances = createSpringFactoriesInstances(type, parameterTypes,
			classLoader, args, names);
	AnnotationAwareOrderComparator.sort(instances);
	return instances;
}

/**
 * 创建spring各种工厂对象实例 使用classLoader动态加载
 * @param type
 * @param parameterTypes
 * @param classLoader
 * @param args
 * @param names
 * @param <T>
 * @return
 */
@SuppressWarnings("unchecked")
private <T> List<T> createSpringFactoriesInstances(Class<T> type,
		Class<?>[] parameterTypes, ClassLoader classLoader, Object[] args,
		Set<String> names) {
	List<T> instances = new ArrayList<>(names.size());
	for (String name : names) {
		try {
			Class<?> instanceClass = ClassUtils.forName(name, classLoader);
			Assert.isAssignable(type, instanceClass);
			Constructor<?> constructor = instanceClass
					.getDeclaredConstructor(parameterTypes);//使用Constructor反射类调用有参构造函数创建实例
			T instance = (T) BeanUtils.instantiateClass(constructor, args);
			instances.add(instance);
		}
		catch (Throwable ex) {
			throw new IllegalArgumentException(
					"Cannot instantiate " + type + " : " + name, ex);
		}
	}
	return instances;
}

private ConfigurableEnvironment getOrCreateEnvironment() { //配置项目的环境属性,Note:在java自带的servlet context初始化之前
	if (this.environment != null) {
		return this.environment;
	}
	switch (this.webApplicationType) {
	case SERVLET:
		return new StandardServletEnvironment();
	case REACTIVE:
		return new StandardReactiveWebEnvironment();
	default:
		return new StandardEnvironment();
	}
}

protected void configureEnvironment(ConfigurableEnvironment environment,
		String[] args) {
	if (this.addConversionService) {
		ConversionService conversionService = ApplicationConversionService
				.getSharedInstance();
		environment.setConversionService(
				(ConfigurableConversionService) conversionService);
	}
	configurePropertySources(environment, args);//添加或替换commandLineArgs在environment中的属性值
	configureProfiles(environment, args);//确保profile被正确配置
}

protected void load(ApplicationContext context, Object[] sources) {
	if (logger.isDebugEnabled()) {
		logger.debug(
				"Loading source " + StringUtils.arrayToCommaDelimitedString(sources));
	}
	BeanDefinitionLoader loader = createBeanDefinitionLoader(
			getBeanDefinitionRegistry(context), sources);//创建一个bean加载器,每个被加载的bean会被自动注册到cache中
	if (this.beanNameGenerator != null) {
		loader.setBeanNameGenerator(this.beanNameGenerator);
	}
	if (this.resourceLoader != null) {
		loader.setResourceLoader(this.resourceLoader);
	}
	if (this.environment != null) {
		loader.setEnvironment(this.environment);
	}
	loader.load();
}

以后我会根据启动过程和你们一起慢慢的解析spring的各种相关的源码,有机会的话实现一个@EnableXXXX注解,已经实现但是有bug

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页