开始入口@SpringBootApplicationpublicclassDemoApplication{publicstaticvoidmain(String[]args){//step.1SpringApplication.run(DemoApplication.class,args);}}实例化SpringApplication对象//step.2publicstaticConfigurableApplicationContextrun(Class>primarySource,String...args){returnrun(newClass[]{primarySource},args);}//step.3//实例化SpringApplication对象并在构造方法中加载一些资源publicstaticConfigurableApplicationContextrun(Class>[]primarySources,String[]args){returnnewSpringApplication(primarySources).run(args);}//step.4publicSpringApplication(Class>...primarySources){this(null,primarySources));}加载运行类信息&判断应用类型&加载初始化器&加载监听器&设置运行主类//step.5@SuppressWarnings({"unchecked","rawtypes"})publicSpringApplication(ResourceLoaderresourceLoader,Class>...primarySources){this.resourceLoader=resourceLoader;Assert.notNull(primarySources,"PrimarySourcesmustnotbenull");//加载运行类信息,这里的primarySources其实就是启动时传入的类this.primarySources=newLinkedHashSet<>(Arrays.asList(primarySources));//判断应用类型,默认servletthis.webApplicationType=WebApplicationType.deduceFromClasspath();this.bootstrapRegistryInitializers=newArrayList<>(getSpringFactoriesInstances(BootstrapRegistryInitializer.class));//加载初始化器setInitializers((Collection)getSpringFactoriesInstances(ApplicationContextInitializerload.class));//ListenersetListeners((Collection)getSpringFactoriesInstances(ApplicationListener.class));//设置运行的主类this.mainApplicationClass=deduceMainApplicationClass();}从getSpringFactoriesInstances()方法可以发现系统使用SpringFactoriesLoader来加载一些预设的配置SpringFactoriesLoader是SpringBoot简化配置的方式,FACTORIES_RESOURCE_LOCATION从静态常量定义可以看出。SpringFactoriesLoader会加载这个目录下定义的一些配置,支持扩展。开发者可以根据导入规则按需配置,不需要像之前那样配置spring写xml文件publicfinalclassSpringFactoriesLoader{/***寻找工厂的位置。*
可以出现在多个JAR文件中。*/publicstaticfinalStringFACTORIES_RESOURCE_LOCATION="META-INF/spring.factories";privatestaticfinalLoglogger=LogFactory.getLog(SpringFactoriesLoader.class);staticfinalMap>>缓存=newConcurrentReferenceHashMap<>();privateSpringFactoriesLoader(){}如果想自定义initializer,需要实现ApplicationContextInitializer接口加载,想自定义Listener,需要实现ApplicationListener接口。以上都需要在resources目录下添加META-INF/spring.factories配置文件,注册自定义初始化器执行启动方法run()//step.6/***运行Spring应用,创建并刷新一个新的*{@linkApplicationContext}。*@paramargs应用程序参数(通常从Javamain方法传递)*@returnarunning{@linkApplicationContext}*/publicConfigurableApplicationContextrun(String...args){//记录开始时间longstartTime=System.nanoTime();//创建引导上下文DefaultBootstrapContextbootstrapContext=createBootstrapContext();//声明应用上下文ConfigurableApplicationContextcontext=null;//设置不显示,仍然启动configureHeadlessProperty();//创建所有Spring运行监听器并发布应用程序启动事件并启用监听器SpringApplicationRunListenerslisteners=getRunListeners(args);listeners.starting(bootstrapContext,this.mainApplicationClass);try{//封装命令行参数ApplicationArgumentsapplicationArguments=newDefaultApplicationArguments(args);//环境准备好加载当前指定环境的运行参数如application-dev.yml或.属性ConfigurableEnvironmentenvironment=prepareEnvironment(listeners,bootstrapContext,applicationArguments);//设置需要忽略的beanconfigureIgnoreBeanInfo(environment);//打印横幅可以通过SpringApplication.setBannerMode(Banner.Mode.OFF)BannerprintedBanner=printBanner;(environment)/创建应用上下文即spring容器context=createApplicationContext();context.setApplicationStartup(this.applicationStartup);//设置bean工厂;在.factories中初始化配置;每个侦听器处理上下文准备事件;设置bean定义加载器;设置资源加载器;设置beanName生成器等prepareContext(bootstrapContext,context,environment,listeners,applicationArguments,printedBanner);//设置容器状态;设置bean工厂;添加后处理器;国际化;调度早期事件;创建网络容器;实例化上述过程中加载的bean等refreshContext(context);//刷新上下文后处理afterRefresh(context,applicationArguments);//记录启动完成的时长DurationtimeTakenToStartup=Duration.ofNanos(System.nanoTime()-startTime);如果(this.logStartupInfo){newStartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(),timeTakenToStartup);}//发布上下文就绪事件listeners.started(context,timeTakenToStartup);//执行自定义运行方法callRunners(context,applicationArguments);}catch(Throwableex){handleRunFailure(context,ex,listeners);抛出新的IllegalStateException(ex);}尝试{持续时间ntimeTakenToReady=Duration.ofNanos(System.nanoTime()-startTime);listeners.ready(上下文,timeTakenToReady);}catch(Throwableex){handleRunFailure(context,ex,null);抛出新的IllegalStateException(ex);}returncontext;}创建bootstrapcontext,可以看到默认没有bootstrapRegistryInitializers。个人理解是这样支持开发者自定义一些需要在spring容器创建之前执行的initializers。设置环境变量可以看到这里加载了一些自定义的环境配置文件创建了一个Spring容器运行时监听扩展函数callRunners(context,applicationArguments)可以在启动完成后执行自定义的内容;实现CommandLineRunner接口的ApplicationRunner接口的实现方法有2种,参考:https://blog.csdn.net/weixin_...https://blog.csdn.net/w200921...