欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

SpringBoot应用启动过程分析

程序员文章站 2023-12-21 08:14:10
 springboot项目通过springapplication.run(app.class, args)来启动: @configuration pu...

 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监听接口实现类,每个类对应了一种事件。

SpringBoot应用启动过程分析

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、启动过程框图

SpringBoot应用启动过程分析

5、接口文档

总结

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

上一篇:

下一篇: