spring boot 启动源码分析

spring boot 启动源码分析

暂时随便写写,以后再整理文章内容。
spring boot 如果不包含springmvc启动的话所做的工作应该是要少很多的。

spring boot 启动会返回一个AnnotationConfigApplicationContext对象
spring boot 启动会返回一个AnnotationConfigApplicationContext对象。

@SpringBootApplication
public class Demo1BootApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext applicationContext = SpringApplication.run(Demo1BootApplication.class, args);
        System.out.println(applicationContext.getClass().getName());
    }

	// 输出 org.springframework.context.annotation.AnnotationConfigApplicationContext
}

开始分析:
启动第一步就是调用SpringApplication.run(Class c, String[] args)这个类方法。

run方法最终会创建一个SpringApplication实例,然后调用实例方法run。

public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
	this.resourceLoader = resourceLoader;
	Assert.notNull(primarySources, "PrimarySources must not be null");
	this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
	// 根据类路径中是否有Servlet或者Reactive判断要使用的ApplicationContext类型。
	this.webApplicationType = WebApplicationType.deduceFromClasspath();
	// 使用SpringFactoriesLoader加载ApplicationContextInitializer实现类, 比java spi机制好的是,不需要为每个扩展建一个类
	setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
	// 使用spring spi机制加载ApplicationListener实现类
	setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
	this.mainApplicationClass = deduceMainApplicationClass();
}
/**
	 * Run the Spring application, creating and refreshing a new
	 * {@link ApplicationContext}.
	 * @param args the application arguments (usually passed from a Java main method)
	 * @return a running {@link ApplicationContext}
	 * 运行spring程序,创建并刷新一个ApplicationContext,然后返回这个类。
	 */
	public ConfigurableApplicationContext run(String... args) {
		// stop watch 秒表的意识,应该是对spring application的运行信息统计
		StopWatch stopWatch = new StopWatch();
		stopWatch.start();
		ConfigurableApplicationContext context = null;
		// spring boot的异常记录类,用于spring启动异常时调用的回调。
		Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
		// 设置System的一个java.awt.headless属性,作用暂时未知
		configureHeadlessProperty();
		// 利用springfactoryloader加载监听器
		SpringApplicationRunListeners listeners = getRunListeners(args);
		// 开始监听
		listeners.starting();
		try {
			// 将命令行参数做了一些处理 比如解析出name以及value 提供了一些便捷函数
			ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
			// 创建执行环境, 如果没有web的情况下创建的是StandradEnvironment
			ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
			configureIgnoreBeanInfo(environment);
			Banner printedBanner = printBanner(environment);
			
			// 核心的一步创建ApplicationContext
			context = createApplicationContext();
			exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
					new Class[] { ConfigurableApplicationContext.class }, context);
			prepareContext(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, exceptionReporters, listeners);
			throw new IllegalStateException(ex);
		}

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

解析SpringApplication.prepareEnvironment方法

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;
	}

// 根据程序类型选择ApplicationContext
protected ConfigurableApplicationContext createApplicationContext() {
	Class<?> contextClass = this.applicationContextClass;
	if (contextClass == null) {
		try {
			switch (this.webApplicationType) {
			case SERVLET:
				contextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS);
				break;
			case REACTIVE:
				contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);
				break;
			default:
				contextClass = Class.forName(DEFAULT_CONTEXT_CLASS);
			}
		}
		catch (ClassNotFoundException ex) {
			throw new IllegalStateException(
					"Unable create a default ApplicationContext, please specify an ApplicationContextClass", ex);
		}
	}
	return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);
}

未完待续。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值