当前位置: 移动技术网 > IT编程>开发语言>Java > SpringBoot应用启动过程分析

SpringBoot应用启动过程分析

2019年07月19日  | 移动技术网IT编程  | 我要评论

 springboot项目通过springapplication.run(app.class, args)来启动:

@configuration
public class app {
 public static void main(string[] args) {
 springapplication.run(app.class, args);
 }
}

接下来,通过源码来看看springapplication.run()方法的执行过程。如果对源码不感兴趣,直接下拉到文章末尾,看启动框图。

1、调用springapplication类的静态方法

 public static configurableapplicationcontext run(object source, string... args) {
  return run(new object[] { source }, args);
 }
 public static configurableapplicationcontext run(object[] sources, string[] args) {
  return new springapplication(sources).run(args);
 }

2、springapplication对象初始化

public springapplication(object... sources) {
  initialize(sources);
 }
 @suppresswarnings({ "unchecked", "rawtypes" })
 private void initialize(object[] sources) {
  if (sources != null && sources.length > 0) {
   this.sources.addall(arrays.aslist(sources));
  }
  // 判断是否为web环境
  this.webenvironment = deducewebenvironment();
  // 找到meta-inf/spring.factories中applicationcontextinitializer所有实现类,并将其实例化
  setinitializers((collection) getspringfactoriesinstances(
    applicationcontextinitializer.class));
  // 找到meta-inf/spring.factories中applicationlistener所有实现类,并将其实例化
  setlisteners((collection) getspringfactoriesinstances(applicationlistener.class));
  // 获取当前main方法类对象,即测试类中的app实例
  this.mainapplicationclass = deducemainapplicationclass();
 }

对象初始化过程中,使用到了getspringfactoriesinstances方法:

 private <t> collection<? extends t> getspringfactoriesinstances(class<t> type) {
  return getspringfactoriesinstances(type, new class<?>[] {});
 }
 private <t> collection<? extends t> getspringfactoriesinstances(class<t> type,
   class<?>[] parametertypes, object... args) {
  classloader classloader = thread.currentthread().getcontextclassloader();
  // use names and ensure unique to protect against duplicates
  // 读取meta-inf/spring.factories指定接口的实现类
  set<string> names = new linkedhashset<string>(
    springfactoriesloader.loadfactorynames(type, classloader));
  list<t> instances = createspringfactoriesinstances(type, parametertypes,
    classloader, args, names);
  annotationawareordercomparator.sort(instances);
  return instances;
 }
 @suppresswarnings("unchecked")
 private <t> list<t> createspringfactoriesinstances(class<t> type,
   class<?>[] parametertypes, classloader classloader, object[] args,
   set<string> names) {
  list<t> instances = new arraylist<t>(names.size());
  for (string name : names) {
   try {
    class<?> instanceclass = classutils.forname(name, classloader);
    assert.isassignable(type, instanceclass);
    constructor<?> constructor = instanceclass.getconstructor(parametertypes);
    t instance = (t) constructor.newinstance(args);
    instances.add(instance);
   }
   catch (throwable ex) {
    throw new illegalargumentexception(
      "cannot instantiate " + type + " : " + name, ex);
   }
  }
  return instances;
 }
 // 读取meta-inf/spring.factories文件
 public static list<string> loadfactorynames(class<?> factoryclass, classloader classloader) {
  string factoryclassname = factoryclass.getname();
  try {
   enumeration<url> urls = (classloader != null ? classloader.getresources(factories_resource_location) :
     classloader.getsystemresources(factories_resource_location));
   list<string> result = new arraylist<string>();
   while (urls.hasmoreelements()) {
    url url = urls.nextelement();
    properties properties = propertiesloaderutils.loadproperties(new urlresource(url));
    string factoryclassnames = properties.getproperty(factoryclassname);
    result.addall(arrays.aslist(stringutils.commadelimitedlisttostringarray(factoryclassnames)));
   }
   return result;
  }
  catch (ioexception ex) {
   throw new illegalargumentexception("unable to load [" + factoryclass.getname() +
     "] factories from location [" + factories_resource_location + "]", ex);
  }
 }
meta-inf/spring.factories文件内容,spring boot版本1.3.6.release
# propertysource loaders
org.springframework.boot.env.propertysourceloader=\
org.springframework.boot.env.propertiespropertysourceloader,\
org.springframework.boot.env.yamlpropertysourceloader
# run listeners
org.springframework.boot.springapplicationrunlistener=\
org.springframework.boot.context.event.eventpublishingrunlistener
# application context initializers
org.springframework.context.applicationcontextinitializer=\
org.springframework.boot.context.configurationwarningsapplicationcontextinitializer,\
org.springframework.boot.context.contextidapplicationcontextinitializer,\
org.springframework.boot.context.config.delegatingapplicationcontextinitializer,\
org.springframework.boot.context.web.serverportinfoapplicationcontextinitializer
# application listeners
org.springframework.context.applicationlistener=\
org.springframework.boot.builder.parentcontextcloserapplicationlistener,\
org.springframework.boot.context.fileencodingapplicationlistener,\
org.springframework.boot.context.config.ansioutputapplicationlistener,\
org.springframework.boot.context.config.configfileapplicationlistener,\
org.springframework.boot.context.config.delegatingapplicationlistener,\
org.springframework.boot.liquibase.liquibaseservicelocatorapplicationlistener,\
org.springframework.boot.logging.classpathloggingapplicationlistener,\
org.springframework.boot.logging.loggingapplicationlistener
# environment post processors
org.springframework.boot.env.environmentpostprocessor=\
org.springframework.boot.cloud.cloudfoundryvcapenvironmentpostprocessor,\
org.springframework.boot.env.springapplicationjsonenvironmentpostprocessor

applicationlistener接口是spring框架的事件监听器,其作用可理解为springapplicationrunlistener发布通知事件时,由applicationlistener负责接收。springapplicationrunlistener接口的实现类就是eventpublishingrunlistener,其在springboot启动过程中,负责注册applicationlistener监听器,在不同时间节点发布不同事件类型,如果有applicationlistener实现类监听了该事件,则接收处理。

public interface springapplicationrunlistener {
 /**
  * 通知监听器,springboot开始启动
  */
 void started();
 /**
  * 通知监听器,环境配置完成
  */
 void environmentprepared(configurableenvironment environment);
 /**
  * 通知监听器,applicationcontext已创建并初始化完成
  */
 void contextprepared(configurableapplicationcontext context);
 /**
  * 通知监听器,applicationcontext已完成ioc配置
  */
 void contextloaded(configurableapplicationcontext context);
 /**
  * 通知监听器,springboot开始完毕
  */
 void finished(configurableapplicationcontext context, throwable exception);
}

附图为applicationlistener监听接口实现类,每个类对应了一种事件。

这里写图片描述

3、springapplication核心run方法

/**
  * 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}
  */
 public configurableapplicationcontext run(string... args) {
  // 任务执行时间监听,记录起止时间差
  stopwatch stopwatch = new stopwatch();
  stopwatch.start();
  configurableapplicationcontext context = null;
  configureheadlessproperty();
  // 启动springapplicationrunlistener监听器
  springapplicationrunlisteners listeners = getrunlisteners(args);
  listeners.started();
  try {
   applicationarguments applicationarguments = new defaultapplicationarguments(
     args);
   // 创建并刷新applicationcontext
   context = createandrefreshcontext(listeners, applicationarguments);
   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, ex);
   throw new illegalstateexception(ex);
  }
 }

这里,需要看看createandrefreshcontext()方法是如何创建并刷新applicationcontext。

private configurableapplicationcontext createandrefreshcontext(
   springapplicationrunlisteners listeners,
   applicationarguments applicationarguments) {
  configurableapplicationcontext context;
  // create and configure the environment
  // 创建并配置运行环境,webenvironment与standardenvironment选其一
  configurableenvironment environment = getorcreateenvironment();
  configureenvironment(environment, applicationarguments.getsourceargs());
  listeners.environmentprepared(environment);
  if (iswebenvironment(environment) && !this.webenvironment) {
   environment = converttostandardenvironment(environment);
  }
  // 是否打印banner,就是启动程序时出现的图形
  if (this.bannermode != banner.mode.off) {
   printbanner(environment);
  }
  // create, load, refresh and run the applicationcontext
  // 创建、装置、刷新、运行applicationcontext
  context = createapplicationcontext();
  context.setenvironment(environment);
  postprocessapplicationcontext(context);
  applyinitializers(context);
  // 通知监听器,applicationcontext创建完毕
  listeners.contextprepared(context);
  if (this.logstartupinfo) {
   logstartupinfo(context.getparent() == null);
   logstartupprofileinfo(context);
  }
  // add boot specific singleton beans
  context.getbeanfactory().registersingleton("springapplicationarguments",
    applicationarguments);
  // load the sources
  // 将beans载入到applicationcontext容器中
  set<object> sources = getsources();
  assert.notempty(sources, "sources must not be empty");
  load(context, sources.toarray(new object[sources.size()]));
  // 通知监听器,beans载入applicationcontext完毕
  listeners.contextloaded(context);
  // refresh the context
  refresh(context);
  if (this.registershutdownhook) {
   try {
    context.registershutdownhook();
   }
   catch (accesscontrolexception ex) {
    // not allowed in some environments.
   }
  }
  return context;
 }

其中利用createapplicationcontext()来实例化applicationcontext对象,即default_web_context_class 、default_context_class两个对象其中一个。

protected configurableapplicationcontext createapplicationcontext() {
  class<?> contextclass = this.applicationcontextclass;
  if (contextclass == null) {
   try {
    contextclass = class.forname(this.webenvironment
      ? default_web_context_class : default_context_class);
   }
   catch (classnotfoundexception ex) {
    throw new illegalstateexception(
      "unable create a default applicationcontext, "
        + "please specify an applicationcontextclass",
      ex);
   }
  }
  return (configurableapplicationcontext) beanutils.instantiate(contextclass);
 }

postprocessapplicationcontext(context)、applyinitializers(context)均为初始化applicationcontext工作。

springboot启动过程分析就先到这里,过程中关注几个对象:

applicationcontext:spring高级容器,与beanfactory类似。

springapplicationrunlistener:sprintboot启动监听器,负责向applicationlistener注册各类事件。

environment:运行环境。

4、启动过程框图

这里写图片描述

5、接口文档

总结

以上所述是小编给大家介绍的springboot应用启动过程分析,希望对大家有所帮助

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网