最近在项目中运用了Springboot,简单的学习了简单的使用,于是想去看看源码是如何实现的。
自己也是第一次尝试看源码,结合了网上的东西和自己的理解,在博客里写点东西,做做积累, 如果其中哪些地方解释有问题,
欢迎老司机指出
参考文章:
1.https://my.oschina.net/u/3081965/blog/916126
2.http://www.cfanz.cn/index.php?c=article&a=read&id=307782
首先不知道从哪里入手,于是我从项目的启动入口开始。
以下就是项目入口代码,很简单,由于是在慕课网上学习的,这里的报名就直接写imooc了(这个为对应springboot的学习地址:http://www.imooc.com/learn/767)
这边的spring-boot版本为1.4.7
package com.imooc;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class GirlApplication {
public static void main(String[] args) {
SpringApplication.run(GirlApplication.class, args);
}
}
@SpringBootApplication 注解暂时不讲,先从下面这个方法开始讲起
SpringApplication.run(GirlApplication.class, args);
点击进去可以看到
/**
* Static helper that can be used to run a {@link SpringApplication} from the
* specified source using default settings.
* @param source the source to load
* @param args the application arguments (usually passed from a Java main method)
* @return the running {@link ApplicationContext}
*/
public static ConfigurableApplicationContext run(Object source, String... args) {
//第一次进入到达这里
return run(new Object[] { source }, args);
}
/**
* Static helper that can be used to run a {@link SpringApplication} from the
* specified sources using default settings and user supplied arguments.
* @param sources the sources to load
* @param args the application arguments (usually passed from a Java main method)
* @return the running {@link ApplicationContext}
*/
public static ConfigurableApplicationContext run(Object[] sources, String[] args) {
//上面方法后进入这里
return new SpringApplication(sources).run(args);
}
首先为第一步,第一步调用第二部的方法,这里主要看下第二步。
第二步这边分为两个步骤去看,第一个步骤为调用SpringApplication类的构造方法创建对象,第二步为调用创建对象的run方法,这里以这两个步骤进行解读。
构建对象:
/**
* Create a new {@link SpringApplication} instance. The application context will load
* beans from the specified sources (see {@link SpringApplication class-level}
* documentation for details. The instance can be customized before calling
* {@link #run(String...)}.
* @param sources the bean sources
* @see #run(Object, String[])
* @see #SpringApplication(ResourceLoader, Object...)
*/
public SpringApplication(Object... sources) {
//调用初始化方法
initialize(sources);
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private void initialize(Object[] sources) {
//将对象资源存放到sources这个linkedSet下,这里的sources就是上诉的com.imooc.GirlController对象
if (sources != null && sources.length > 0) {
this.sources.addAll(Arrays.asList(sources));
}
//这里暂时没有看懂,从字面上来看,是判断是否有web环境
this.webEnvironment = deduceWebEnvironment();
//实例化Initializer,initializers成员变量,是一个ApplicationContextInitializer类型对象的集合。
//顾名思义,ApplicationContextInitializer是一个可以用来初始化ApplicationContext的接口。
//初始化ApplicationContext的Initializer程序
//boot包下的META-INF/spring.factories
0 = "org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer"
1 = "org.springframework.boot.context.ContextIdApplicationContextInitializer"
2 = "org.springframework.boot.context.config.DelegatingApplicationContextInitializer"
3 = "org.springframework.boot.context.web.ServerPortInfoApplicationContextInitializer"
//autoconfigure下的META-INF/spring.factories
4 = "org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer"
5 = "org.springframework.boot.autoconfigure.logging.AutoConfigurationReportLoggingInitializer"
setInitializers((Collection) getSpringFactoriesInstances(
ApplicationContextInitializer.class));
//实例化监听器
//初始化 ApplicationListener boot下9个,autoconfigure一个
//0 = "org.springframework.boot.ClearCachesApplicationListener"
//1 = "org.springframework.boot.builder.ParentContextCloserApplicationListener"
//2 = "org.springframework.boot.context.FileEncodingApplicationListener"
//找出main方法的全类名并返回其实例并设置到SpringApplication的this.mainApplicationClass完成初始化
this.mainApplicationClass = deduceMainApplicationClass();
}
这里附上deduceWebEnvironment()方法的实现,其中WEB_ENVIRONMENT_CLASSES的值为
private static final String[] WEB_ENVIRONMENT_CLASSES = { "javax.servlet.Servlet",
"org.springframework.web.context.ConfigurableWebApplicationContext" };
private boolean deduceWebEnvironment() {
for (String className : WEB_ENVIRONMENT_CLASSES) {
if (!ClassUtils.isPresent(className, null)) {
return false;
}
}
return true;
}
上面SpringApplication的初始化动作已经做完了,然后看下run方法里做了哪些操作。
public ConfigurableApplicationContext run(String... args) {
//StopWatch是一个监视器,主要是用来记录程序的运行时间,这里是用来记录程序启动所需要的时间 StopWatch stopWatch = new StopWatch(); stopWatch.start(); ConfigurableApplicationContext context = null; FailureAnalyzers analyzers = null; configureHeadlessProperty(); SpringApplicationRunListeners listeners = getRunListeners(args); listeners.started(); try { ApplicationArguments applicationArguments = new DefaultApplicationArguments( args); ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments); Banner printedBanner = printBanner(environment); context = createApplicationContext(); analyzers = new FailureAnalyzers(context); prepareContext(context, environment, listeners, applicationArguments, printedBanner); refreshContext(context); afterRefresh(context, applicationArguments); listeners.finished(context, null); stopWatch.stop(); if (this.logStartupInfo) { new StartupInfoLogger(this.mainApplicationClass) .logStarted(getApplicationLog(), stopWatch); } return context; } catch (Throwable ex) { handleRunFailure(context, listeners, analyzers, ex); throw new IllegalStateException(ex); } }