public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
return run(new Class<?>[] { primarySource }, args);
}
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
return new SpringApplication(primarySources).run(args);
}
public SpringApplication(Class<?>... primarySources) {
this(null, primarySources);
}
public ConfigurableApplicationContext run(String... args) {
/**
* 创建并且运行一个秒表总运行时间和每个命名任务的运行时间。
*/
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
configureHeadlessProperty();
SpringApplicationRunListeners listeners = getRunListeners(args);
//运行所有的监听器的starting
listeners.starting();
try {
// 解析args 为SimpleCommandLinePropertySource并且保存args
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
configureIgnoreBeanInfo(environment);
// 打印骚东西
Banner printedBanner = printBanner(environment);
// 根据webApplicationType 返回对应的ApplicationContext
context = createApplicationContext();
// 获取自定义报告列表 默认有FailureAnalysis
exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
refreshContext(context);
afterRefresh(context, applicationArguments);
// 停止stopWatch里面当前任务 计算总时间
stopWatch.stop();
// 打印springboot启动的时间和jvm
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
}
// 循环调用SpringApplicationRunListener.started
listeners.started(context);
// 执行所有的ApplicationRunner和CommandLineRunner
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, listeners);
throw new IllegalStateException(ex);
}
try {
// 执行所有SpringApplicationRunListener.running
listeners.running(context);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, null);
throw new IllegalStateException(ex);
}
return context;
}
1.configureHeadlessProperty()
/**
* 从系统变量获取java.awt.headless的值
* 如果没有就用当前的值
*/
private void configureHeadlessProperty() {
System.setProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS,
System.getProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS, Boolean.toString(this.headless)));
}
2.getRunListeners(String[] args)
/**
* 获取spring工厂的所有实现了SpringApplicationRunListener的类
* 构建一个SpringApplicationRunListeners集合,储存了SpringApplication的log
* @param args
* @return
*/
private SpringApplicationRunListeners getRunListeners(String[] args) {
Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
return new SpringApplicationRunListeners(logger,
getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args));
}
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
// 获取类加载器
ClassLoader classLoader = getClassLoader();
//使用名称并确保唯一以防止重复
Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
// 创建spring工厂的实例对象
List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
// 给实现了PriorityOrdered 的排序
AnnotationAwareOrderComparator.sort(instances);
return instances;
}
3.prepareEnvironment(listeners, applicationArguments)
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments) {
// 创建和配置环境
ConfigurableEnvironment environment = getOrCreateEnvironment();
configureEnvironment(environment, applicationArguments.getSourceArgs());
ConfigurationPropertySources.attach(environment);
// 循环执行listener的environmentPrepared方法
listeners.environmentPrepared(environment);
// 将环境绑定到{@link SpringApplication}。
bindToSpringApplication(environment);
//再判断下environment的类型
if (!this.isCustomEnvironment) {
environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment,
deduceEnvironmentClass());
}
ConfigurationPropertySources.attach(environment);
return environment;
}
protected void configureEnvironment(ConfigurableEnvironment environment, String[] args) {
if (this.addConversionService) {
// 返回ApplicationConversionService的实例
ConversionService conversionService = ApplicationConversionService.getSharedInstance();
// 关联environment
environment.setConversionService((ConfigurableConversionService) conversionService);
}
configurePropertySources(environment, args);
// 更新environment里面的ActiveProfiles
configureProfiles(environment, args);
}
protected void configurePropertySources(ConfigurableEnvironment environment, String[] args) {
MutablePropertySources sources = environment.getPropertySources();
// 如果默认的Properties不为null和空 就添加到sources末尾
if (this.defaultProperties != null && !this.defaultProperties.isEmpty()) {
sources.addLast(new MapPropertySource("defaultProperties", this.defaultProperties));
}
// 是否添加命令行的参数配置
if (this.addCommandLineProperties && args.length > 0) {
String name = CommandLinePropertySource.COMMAND_LINE_PROPERTY_SOURCE_NAME;
/**
* 判断里面是否已经有commandLineArgs
* 用给定的属性源对象用给定的名称替换属性源。
*/
if (sources.contains(name)) {
PropertySource<?> source = sources.get(name);
CompositePropertySource composite = new CompositePropertySource(name);
composite.addPropertySource(
new SimpleCommandLinePropertySource("springApplicationCommandLineArgs", args));
composite.addPropertySource(source);
sources.replace(name, composite);
}
else {
// 将commandLineArgs添加到第一个
sources.addFirst(new SimpleCommandLinePropertySource(args));
}
}
}
protected void configureProfiles(ConfigurableEnvironment environment, String[] args) {
Set<String> profiles = new LinkedHashSet<>(this.additionalProfiles);
profiles.addAll(Arrays.asList(environment.getActiveProfiles()));
environment.setActiveProfiles(StringUtils.toStringArray(profiles));
}
public static void attach(Environment environment) {
// 判断environment是否为ConfigurableEnvironment的实例对象 不是就抛出异常
Assert.isInstanceOf(ConfigurableEnvironment.class, environment);
MutablePropertySources sources = ((ConfigurableEnvironment) environment).getPropertySources();
// 获取configurationProperties
PropertySource<?> attached = sources.get(ATTACHED_PROPERTY_SOURCE_NAME);
//
/**
* 如果attached不为null 并且和sources里面的不一样 就删除重新添加到sources的头上面
* 为null的话就直接添加到sources头上面
*/
if (attached != null && attached.getSource() != sources) {
sources.remove(ATTACHED_PROPERTY_SOURCE_NAME);
attached = null;
}
if (attached == null) {
sources.addFirst(new ConfigurationPropertySourcesPropertySource(ATTACHED_PROPERTY_SOURCE_NAME,
new SpringConfigurationPropertySources(sources)));
}
}
/**
* 将环境绑定到{@link SpringApplication}。
* @param environment the environment to bind
*/
protected void bindToSpringApplication(ConfigurableEnvironment environment) {
try {
Binder.get(environment).bind("spring.main", Bindable.ofInstance(this));
}
catch (Exception ex) {
throw new IllegalStateException("Cannot bind to SpringApplication", ex);
}
}
4.configureIgnoreBeanInfo(environment)
private void configureIgnoreBeanInfo(ConfigurableEnvironment environment) {
/**
* 判断系统环境是否有spring.beaninfo.ignore的值
* 没有的话从environment里面获取,如果environment里面为null 就返回true
*/
if (System.getProperty(CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME) == null) {
Boolean ignore = environment.getProperty("spring.beaninfo.ignore", Boolean.class, Boolean.TRUE);
System.setProperty(CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME, ignore.toString());
}
}
5.printBanner(environment)
private Banner getBanner(Environment environment) {
Banners banners = new Banners();
/**
* 判断是否有banner."gif", "jpg", "png"其中的一个
* 有就构建ImageBanner添加到banners里面
*/
banners.addIfNotNull(getImageBanner(environment));
/**
* 判断是否有banner.txt
* 有就构建ResourceBanner添加到banners里面
*/
banners.addIfNotNull(getTextBanner(environment));
// 判断banners不为空就直接返回
if (banners.hasAtLeastOneBanner()) {
return banners;
}
// 如果设置了错误回调Banner就返回
if (this.fallbackBanner != null) {
return this.fallbackBanner;
}
//返回默认的SpringBootBanner
return DEFAULT_BANNER;
}
6.createApplicationContext()
/**
* 用于创建{@link ApplicationContext}的策略方法。
* 默认情况下,此方法将使用任何明确设置的应用程序上下文或应用程序上下文类,然后再降为合适的默认值。
* @return the application context (not yet refreshed)
* @see #setApplicationContextClass(Class)
*/
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);
}
7.getSpringFactoriesInstances(SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context)
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
// 获取类加载器
ClassLoader classLoader = getClassLoader();
//使用名称并确保唯一以防止重复
Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
// 创建spring工厂的实例对象
List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
// 给实现了PriorityOrdered 的排序
AnnotationAwareOrderComparator.sort(instances);
return instances;
}
8.prepareContext(context, environment, listeners, applicationArguments, printedBanner)
private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment,
SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
/**
*
* 将environment委托给基础的 {@link AnnotatedBeanDefinitionReader}{@link ClassPathBeanDefinitionScanner}成员。
* 和AbstractApplicationContext成员。
*/
context.setEnvironment(environment);
postProcessApplicationContext(context);
// 循环调用ApplicationContextInitializer.initialize
applyInitializers(context);
// 循环调用监听器的SpringApplicationRunListener.contextPrepared
listeners.contextPrepared(context);
if (this.logStartupInfo) {
// 打印 info和debug级别日志 包含pid ApplicationName context等等
logStartupInfo(context.getParent() == null);
// 打印 info级别日志 对activeProfiles和defaultProfiles的记录
logStartupProfileInfo(context);
}
// 添加引导特别的单例bean
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
if (printedBanner != null) {
beanFactory.registerSingleton("springBootBanner", printedBanner);
}
if (beanFactory instanceof DefaultListableBeanFactory) {
// 设置是否允许重新注册覆盖相同名称的Bean
((DefaultListableBeanFactory) beanFactory)
.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
/**
* 是否懒加载是的话就添加Bean工厂后置处理器 LazyInitializationBeanFactoryPostProcessor
*/
if (this.lazyInitialization) {
context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
}
// 返回primarySources和sources的不可变set集合
Set<Object> sources = getAllSources();
Assert.notEmpty(sources, "Sources must not be empty");
// registerBeanDefinition逻辑
load(context, sources.toArray(new Object[0]));
// 循环执行SpringApplicationRunListener.contextLoaded
listeners.contextLoaded(context);
}
protected void load(ApplicationContext context, Object[] sources) {
if (logger.isDebugEnabled()) {
logger.debug("Loading source " + StringUtils.arrayToCommaDelimitedString(sources));
}
//构建一个包括XML和JavaConfig)加载bean定义loader
BeanDefinitionLoader loader = createBeanDefinitionLoader(getBeanDefinitionRegistry(context), sources);
// 关联Bean名称 命名策略
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();
}
private int load(Class<?> source) {
if (isGroovyPresent() && GroovyBeanDefinitionSource.class.isAssignableFrom(source)) {
// Any GroovyLoaders added in beans{} DSL can contribute beans here
GroovyBeanDefinitionSource loader = BeanUtils.instantiateClass(source, GroovyBeanDefinitionSource.class);
load(loader);
}
if (isEligible(source)) {
//注册BeanDefinition的实现
this.annotatedReader.register(source);
return 1;
}
return 0;
}
9.refreshContext(context)
private void refreshContext(ConfigurableApplicationContext context) {
// 是否注册关闭的钩子 看过tomcat源码的这里就比较熟悉了
if (this.registerShutdownHook) {
try {
context.registerShutdownHook();
}
catch (AccessControlException ex) {
// 在某些环境中不允许使用。
}
}
refresh((ApplicationContext) context);
}
/**
* 刷新基础的{@link ApplicationContext}。
* @param applicationContext the application context to refresh
*/
protected void refresh(ConfigurableApplicationContext applicationContext) {
applicationContext.refresh();
}
public final void refresh() throws BeansException, IllegalStateException {
try {
/**
* AbstractApplicationContext.refresh() 逻辑
* 主要看子类实现onRefresh()
*/
super.refresh();
}
catch (RuntimeException ex) {
WebServer webServer = this.webServer;
if (webServer != null) {
webServer.stop();
}
throw ex;
}
}
protected void onRefresh() {
// 初始化GenericWebApplicationContext主题功能
super.onRefresh();
try {
createWebServer();
}
catch (Throwable ex) {
throw new ApplicationContextException("Unable to start web server", ex);
}
}
createWebServer()创建内置Web容器
private void createWebServer() {
WebServer webServer = this.webServer;
ServletContext servletContext = getServletContext();
if (webServer == null && servletContext == null) {
ServletWebServerFactory factory = getWebServerFactory();
this.webServer = factory.getWebServer(getSelfInitializer());
getBeanFactory().registerSingleton("webServerGracefulShutdown",
new WebServerGracefulShutdownLifecycle(this.webServer));
// 通过spring的生命中期联动Web容器的启动和停止
getBeanFactory().registerSingleton("webServerStartStop",
new WebServerStartStopLifecycle(this, this.webServer));
}
else if (servletContext != null) {
try {
getSelfInitializer().onStartup(servletContext);
}
catch (ServletException ex) {
throw new ApplicationContextException("Cannot initialize servlet context", ex);
}
}
initPropertySources();
}
/**
*返回用于创建嵌入式{@link WebServer}的{@link ServletWebServerFactory}。
* 默认情况下,此方法在上下文本身中搜索合适的bean。
* @return a {@link ServletWebServerFactory} (never {@code null})
*/
protected ServletWebServerFactory getWebServerFactory() {
/**
* 使用Bean名称,这样我们就不会考虑层次结构
* 做了校验不能为0也不能大于1
*/
String[] beanNames = getBeanFactory().getBeanNamesForType(ServletWebServerFactory.class);
if (beanNames.length == 0) {
throw new ApplicationContextException("Unable to start ServletWebServerApplicationContext due to missing "
+ "ServletWebServerFactory bean.");
}
if (beanNames.length > 1) {
throw new ApplicationContextException("Unable to start ServletWebServerApplicationContext due to multiple "
+ "ServletWebServerFactory beans : " + StringUtils.arrayToCommaDelimitedString(beanNames));
}
return getBeanFactory().getBean(beanNames[0], ServletWebServerFactory.class);
}
WebServerStartStopLifecycle负责Web容器的启动和停止
/**
* {@link SmartLifecycle},以在{@link ServletWebServerApplicationContext}中启动和停止{@link WebServer}。
*
* @author Andy Wilkinson
*/
class WebServerStartStopLifecycle implements SmartLifecycle {
private final ServletWebServerApplicationContext applicationContext;
private final WebServer webServer;
private volatile boolean running;
WebServerStartStopLifecycle(ServletWebServerApplicationContext applicationContext, WebServer webServer) {
this.applicationContext = applicationContext;
this.webServer = webServer;
}
@Override
public void start() {
this.webServer.start();
this.running = true;
this.applicationContext
.publishEvent(new ServletWebServerInitializedEvent(this.webServer, this.applicationContext));
}
@Override
public void stop() {
this.webServer.stop();
}
@Override
public boolean isRunning() {
return this.running;
}
@Override
public int getPhase() {
return Integer.MAX_VALUE - 1;
}
}
public void start() throws WebServerException {
synchronized (this.monitor) {
if (this.started) {
return;
}
try {
//启动关联服务的连接器
addPreviouslyRemovedConnectors();
Connector connector = this.tomcat.getConnector();
if (connector != null && this.autoStart) {
performDeferredLoadOnStartup();
}
checkThatConnectorsHaveStarted();
this.started = true;
logger.info("Tomcat started on port(s): " + getPortsDescription(true) + " with context path '"
+ getContextPath() + "'");
}
catch (ConnectorStartFailedException ex) {
stopSilently();
throw ex;
}
catch (Exception ex) {
PortInUseException.throwIfPortBindingException(ex, () -> this.tomcat.getConnector().getPort());
throw new WebServerException("Unable to start embedded Tomcat server", ex);
}
finally {
Context context = findContext();
ContextBindings.unbindClassLoader(context, context.getNamingToken(), getClass().getClassLoader());
}
}
}
10.afterRefresh(context, applicationArguments)
/**
* 在刷新上下文后调用。
* @param context the application context
* @param args the application arguments
*/
protected void afterRefresh(ConfigurableApplicationContext context, ApplicationArguments args) {
}