亚游,看尚能够在此次双12电商大促中斩获全渠道破66000台的销量佳绩,首先得益于看尚产品的精准定位。继双11促销战之后,看尚再度携旗下四款热销机型征战双12战场,看尚超能电视C42S、V43、V50、F55S四款产品分别瞄准不同的用户群体、直击不同家庭的使用需求。其中,看尚超能电视C42S大小适中,客厅、卧室两相宜;看尚超能电视V43是43英寸4K机的实力代表,也是掀起4K普及风暴的热销机型;看尚超能电视V50以高配置和高品质著称,性能突出、画质臻美,拥有大量4K片源,被认为是“客厅专属私人影院”;看尚超能电视F55S则瞄准了55英寸这个家庭电视的黄金尺寸,成为用户换购大屏4K电视的首选。

而12306网站春运车票预售期缩短为30天,有人认为这将影响春运抢票,但这种判断依据错误地把购票时间和售票数量混淆了。事实上,售票缩短的原因是部分新线即将开通运营,运力得到提升,旅客在春运时能够获得更多的选择机会。时间缩短,但车票增加,这种辩证关系很容易看清楚。焦虑与否,无疑要靠自己把握。 白手起家做什么好该公司还计划将由奥地利的Magna Steyr汽车公司来协助生产即将问世的I-Pace纯电动SUV。(实习编译:夏云云 审稿:刘洋)

发布于 2018-03-24 07:57:11 | 130 次阅读 | 评论: 0 | 来源: 网友投递

这里有新鲜出炉的精品教程,程序狗速度看过来!

Spring Boot

Spring Boot 项目旨在简化创建产品级的 Spring 应用和服务。你可通过它来选择不同的 Spring 平台。可创建独立的 Java 应用和 Web 应用,同时提供了命令行工具来允许 'spring scripts'.


这篇文章主要介绍了SpringBoot应用启动过程分析,需要的朋友可以参考下

 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、接口文档

亚游/docs0b0aspring0b0aio/spring-framework/docs/current/javadoc-api/

总结

以上所述是小编给大家介绍的SpringBoot应用启动过程分析,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对PHPERZ网站的支持!



相关阅读 :
SpringBoot应用启动过程分析
SpringBoot应用启动过程分析
SpringBoot应用启动过程分析
Spring Boot启动过程完全解析(二)
Spring Boot启动过程完全解析(一)
详解spring-boot集成elasticsearch及其简单应用
Spring Boot Web应用开发 CORS 跨域请求支持
详解SpringBoot 创建定时任务(配合数据库动态执行)
springboot前后台数据交互的示例代码
详解SpringBoot 使用Spring Initializr 快速构建工程(官方推荐)
SpringBoot创建maven多模块项目实战代码
SpringBoot mail中文附件乱码的解决方法
最新网友评论  共有(0)条评论 发布评论 返回顶部

Copyright © 2007-2017 亚游 All Rights Reserved   冀ICP备14009818号  亚游  广告服务
火币网创始人李林:杜均没有参与过火币pro任何业务 特斯拉股价周三一度下跌3.9% 已连续四个交易日下跌 彭博社:130亿美元的中国电竞市场 腾讯只想当主演 上海女排险胜江苏总比分3-1晋级 将与天津争冠 美官员称美国支持中国加入WTO是错误?王国庆回应 陕西:公立医院领导薪酬不超医务人员平均薪酬5倍 进球gif-郑铮精准长传制导 塔尔德利推射破僵局 鲁媒:山东将与凯撒商讨续约 欲引入国字号球员 太累!上港10人出勤超700分钟 别忘去年怎么崩盘 科学家绘制果蝇大脑高清图 追踪神经元之间的连接 同在火场 中国武警舍己美国警察舍人 传销组织非法拘禁他人致2人跳河死亡1人跳楼重伤
3月13日上市公司晚间公告速递 央行参事盛松成:中美贸易逆差实际上没那么大 伊朗以色列交火后伊外长将于本周日抵京?中方回应 菲律宾取消一暂停采矿禁令 盼助明确矿业发展前景 华盛顿赛库兹娃完胜晋级 韩馨蕴遭本土球员横扫 刘强东:遏制新官不理旧账行为不亚于一次反腐斗争 特朗普正式签署关税法令 钢铝分别征收25%和10%关税 拜仁今年没有中国行?拜仁官宣今夏赴美国热身 华融“去赖小民化”进行时:聚焦不良资产经营主业 相似度100%!詹姆斯13岁儿子这一扣看哭科比 齐达内:打巴黎并不是决战 没有内马尔依然危险 菲律宾启动修宪 杜特尔特或可变换身份长期执政
联通王晓初:运营商提速降费或自7月1日起执行 保本基金到期转型:国联安安稳今年第14只到期产品 迎接美使馆开张 耶路撒冷最好足球队更名\"特朗普\" 山西打掉11人盗墓恶势力团伙 盗掘贩卖文物523件 MH370调查组8月3日将在北京举行记者会 张建民任国家烟草专卖局局长 陈杰任同济大学校长 全国人大代表建议:将元宵节纳入国家法定节假日 纽交所支付1400万美元的罚金 和解多项违规行为指控 福特森期待总决赛对位郭艾伦 大金链赌局来了 不怕死想发财的兄弟进 加盟店排行榜 马云说未来的热门行业 广东水库抓到一只女鬼 亚游