【酒楼溯源码燕窝多少钱一克】【linux怎么查询源码】【交友开发源码】webapp启动源码_web应用源码

时间:2024-12-22 20:56:20 来源:c 并发服务源码 编辑:德州源码网页

1.springboot启动类原理?
2.滴滴 Web 移动端组件库 cube-ui 开源

webapp启动源码_web应用源码

springboot启动类原理?

       SpringbootBatch的启动原理-Configuration

       Springboot整合了web和batch,但是他们肯定不是同一条路,在springboot中,会推断当前的运行环境。this.webApplicationType=WebApplicationType.deduceFromClasspath();

       ä»Žä¸Šæ–‡å¯ä»¥çœ‹å‡ºï¼ŒSpring尝试从classpath里找到特征类,来判断当前app是什么类型。当然这种判断是有局限性的,有可能是transitive带进来一个带有servlet的类被当成了WebApplicationType.SERVLET,实际上是个WebApplicationType.NONE;。如果不想以web运行就是想运行batch可以在application.properties强行指定WebApplicationType

       å…·ä½“发生作用的请看下面的stacktrace

       å½“一个batchapplication需要启动,需要配置JobRepository,Datasource等等,所有的开始都来自一个annotation@EnableBatchProcessing

       å½“加入@EnableBatchProcessing时,BatchConfigurationSelector开始启动,怎么启动的大家可以参考下面的stacktrace。

       import类主要是由ConfigurationClassPostProcessor来实现的。当BatchConfigurationSelector被调用的时候,我们可以看到他有两条支路。

       é‚£ä¹ˆè¿™ä¸¤æ¡è·¯æœ‰å•¥ä¸åŒå‘¢ã€‚主要是job定义的方式不同。

       modular=true的情况下,下面是一个例子

       å¯ä»¥æœ‰å¤šä¸ªå­ApplicationContextFactory,这样好处是在除了job大家不可以重复,因为是在不同的context里,其他的step,reader,writer,processor,mapper,以及所有的bean等等都可以重名。

       é‚£ä¸ºä»€ä¹ˆJob不可以重复,是因为虽然可以重复,但是如果job也重复,对用户来讲太不友好了。用户可能不知道自己配的是哪个context的job。具体为什么可以重名要看看GenericApplicationContextFactory的实现。

       å½“GenericApplicationContextFactory::createApplicationContext,启动会触发ApplicationContextHelper的构造函数从而调用loadConfiguration(config)把定义的bean加入到context里。那么有个问题,parent在哪里设置,createApplicationContext是什么时候调用的。

       æˆ‘们继续看ModularConfiguration

       ä»ŽModular的角度来看首先他可以外部注入一个Configurer,如果没有就选择DefaultBatchConfigurer,如果有多个选择则会抛出。

       å½“然Datasource也可以选择外部注入,或者由DefaultBatchConfigurer::initialize方法SimpleJobLauncher,JobRepository和JobExplorer都是由FactoryBean的方式实现的。

       åœ¨è¿™ä¸ªDefaultBatchConfigurer中可以看到JobLauncher的类型是

       initialize里MapJobRepositoryFactoryBean这个可以重点读一下。首先用FactoryBean的模式实现了一个ProxyBean,如果想了解FactoryBean的用法,这是个典型的例子。但是这个FactoryBean是以api行为直接调用的,并没有注册到Spring的context中。

       é…ç½®å¥½job需要的jobRepository,jobLauncher等那么重点来了,下面的AutomaticJobRegistrar就是来处理ApplicationContextFactory

       è¿™ä¸ªé€»è¾‘是把所有的ApplicationContextFactory的beaninstance放入到AutomaticJobRegistrar里去。这就回到了第一个问题,parentcontext是什么时候放进去的。就是在

       context.getBeansOfType(ApplicationContextFactory.class)请看下面的调用栈,在ApplicationContextAwareProcessor里会自动把parentcontext注入。

       ä½†æ˜¯æ”¾è¿›åŽ»å•¥æ—¶å€™ç”¨å‘¢ï¼Ÿæˆ‘们看一下AutomaticJobRegistrar

       åŽŸæ¥AutomaticJobRegistrar是个Smartlifecycle,从Smartlifecycle的细节可以从SpringbootSmartlifecycle来得知。它就是在所有bean都初始化结束后开始进行的一个阶段。在这个start方法中,开始遍历所有的ApplicationContextFactory,来进行加载。从上文这个jobLoader是DefaultJobLoader。

       é‚£ä¹ˆå¯ä»¥çœ‹çœ‹DefaultJobLoader::doLoad方法

       è¿™é‡Œæœ‰å‡ ä¸ªå…³é”®è°ƒç”¨ç¬¬ä¸€ä¸ªæ˜¯createApplicationContext,把context里定义的全部加载到Springcontext里去,这就满足了GenericApplicationContextFactory工作的两个条件。第二个是doRegister(context,job)里jobRegistry.register(jobFactory);

       æˆ‘们看一下JobRepository的实现MapJobRegistry::register方法,在这里就把jobname和jobFactory的键值对存储起来了。

       è¿™æ ·å°±å¯ä»¥é€šè¿‡JobRepository这个bean拿到所有注册的job了。

       å’±ä»¬å†å›žæ¥çœ‹@EnableBatchProcessing这个annotation,当没有设定modular的时候是比较简单的,只是实现了一个proxybased的Job的bean。

       åŒæ ·ä¹Ÿåªæœ‰BatchConfigurer来配置。这个逻辑和Modular是一样的。从这两个配置知道,Modular注册了在子context的配置,并且加载。但是当以正常bean的方式存在的,是怎么读进来的呢。这时候就要看JobRegistryBeanPostProcessor

       è¿™ä¸ªpostProcessAfterInitialization方法里,对每个job类型的bean,jobRegistry加入了ReferenceJobFactory。这样所有的以bean的方式定义的都可以通过jobRegistry获得。

SpringBootStater原理

       ä¸€.SpringBoot的好处

       1.依赖管理:可插拔式的组件管理,当需要某个组件时,只需要引入相关stater即可,不需要再手动引入各个jar包,避免了包遗漏、包冲突等不必要的问题。开发人员可以专注于业务开发,

       2.自动配置:遵从"约定优于配置"的原则,开发人员可以在少量配置或者不配置的情况下,使用某组件。

       å¤§å¤§é™ä½Žé¡¹ç›®æ­å»ºåŠç»„件引入的成本,开发人员可以专注于业务开发,避免繁杂的配置和大量的jar包管理。

       äºŒ.实现原理

       è¦å¼•å…¥æŸç»„件,无非要做两件事。一是引入jar包即pom文件引入stater;二就是编写配置文件,使用Java配置的情况下就是编写一系列@Configuration注解标注的类。那么SpringBoot是怎么来引入这些配置类的呢?就需要我们深入SpringBoot启动类一探究竟。

       SpringBoot启动类上面会有@SpringBootApplication注解,这是SpringBoot中最重要的一个注解,是实现自动配置的关键。@SpringBootApplication是一个租合注解,主要由@SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan三部分组成。

@SpringBootConfiguration表明该类是一个配置类。

@EnableAutoConfiguration由@AutoConfigurationPackage和@Import(AutoConfigurationImportSelector.class)组成。@AutoConfigurationPackage由@Import(AutoconfigurationPackages.Registrar.class)组成,向Bean容器中注册一个AutoConfigurationPackages类,该类持有basePackage,目前我发现的作用是在MyBatis扫描注册Mapper时作为包扫描路径。

       @AutoConfigurationPackage的执行流程如下图:

@Import(AutoConfigurationImportSelector.class)是启动自动配置的核心。这里还有一个小插曲,一直在看AutoConfigurationImportSelector的selectImports方法,却发现没有被调用,以为是demo项目问题,去真实项目中debug断点,发现也没有进入,瞬间懵逼。。。继续跟踪发现执行流程如下:

       SpringBoot启动原理分析

       è‡ªåŠ¨é…ç½®æ ¸å¿ƒç±»SpringFactoriesLoader

       ä¸Šé¢åœ¨è¯´@EnableAutoConfiguration的时候有说META-INF下的spring.factories文件,那么这个文件是怎么被spring加载到的呢,其实就是SpringFactoriesLoader类。

       SpringFactoriesLoader是一个供Spring内部使用的通用工厂装载器,SpringFactoriesLoader里有两个方法,

       åœ¨è¿™ä¸ªSpringBoot应用启动过程中,SpringFactoriesLoader做了以下几件事:

       åŠ è½½æ‰€æœ‰META-INF/spring.factories中的Initializer

       åŠ è½½æ‰€æœ‰META-INF/spring.factories中的Listener

       åŠ è½½EnvironmentPostProcessor(允许在Spring应用构建之前定制环境配置)

       æŽ¥ä¸‹æ¥åŠ è½½Properties和YAML的PropertySourceLoader(针对SpringBoot的两种配置文件的加载器)

       å„种异常情况的FailureAnalyzer(异常解释器)

       åŠ è½½SpringBoot内部实现的各种AutoConfiguration

       æ¨¡æ¿å¼•æ“ŽTemplateAvailabilityProvider(如Freemarker、Thymeleaf、Jsp、Velocity等)

       æ€»å¾—来说,SpringFactoriesLoader和@EnableAutoConfiguration配合起来,整体功能就是查找spring.factories文件,加载自动配置类。

       æ•´ä½“启动流程

       åœ¨æˆ‘们执行入口类的main方法之后,运行SpringApplication.run,后面new了一个SpringApplication对象,然后执行它的run方法。

       åˆå§‹åŒ–SpringApplicationç±»

       åˆ›å»ºä¸€ä¸ªSpringApplication对象时,会调用它自己的initialize方法

       æ‰§è¡Œæ ¸å¿ƒrun方法

       åˆå§‹åŒ–initialize方法执行完之后,会调用run方法,开始启动SpringBoot。

       é¦–先遍历执行所有通过SpringFactoriesLoader,在当前classpath下的META-INF/spring.factories中查找所有可用的SpringApplicationRunListeners并实例化。调用它们的starting()方法,通知这些监听器SpringBoot应用启动。

       åˆ›å»ºå¹¶é…ç½®å½“前SpringBoot应用将要使用的Environment,包括当前有效的PropertySource以及Profile。

       éåŽ†è°ƒç”¨æ‰€æœ‰çš„SpringApplicationRunListeners的environmentPrepared()的方法,通知这些监听器SpringBoot应用的Environment已经完成初始化。

       æ‰“印SpringBoot应用的banner,SpringApplication的showBanner属性为true时,如果classpath下存在banner.txt文件,则打印其内容,否则打印默认banner。

       æ ¹æ®å¯åŠ¨æ—¶è®¾ç½®çš„applicationContextClass和在initialize方法设置的webEnvironment,创建对应的applicationContext。

       åˆ›å»ºå¼‚常解析器,用在启动中发生异常的时候进行异常处理(包括记录日志、释放资源等)。

       è®¾ç½®SpringBoot的Environment,注册SpringBean名称的序列化器BeanNameGenerator,并设置资源加载器ResourceLoader,通过SpringFactoriesLoader加载ApplicationContextInitializer初始化器,调用initialize方法,对创建的ApplicationContext进一步初始化。

       è°ƒç”¨æ‰€æœ‰çš„SpringApplicationRunListeners的contextPrepared方法,通知这些Listener当前ApplicationContext已经创建完毕。

       æœ€æ ¸å¿ƒçš„一步,将之前通过@EnableAutoConfiguration获取的所有配置以及其他形式的IoC容器配置加载到已经准备完毕的ApplicationContext。

       è°ƒç”¨æ‰€æœ‰çš„SpringApplicationRunListener的contextLoaded方法,加载准备完毕的ApplicationContext。

       è°ƒç”¨refreshContext,注册一个关闭Spring容器的钩子ShutdownHook,当程序在停止的时候释放资源(包括:销毁Bean,关闭SpringBean的创建工厂等)

       æ³¨ï¼šé’©å­å¯ä»¥åœ¨ä»¥ä¸‹å‡ ç§åœºæ™¯ä¸­è¢«è°ƒç”¨ï¼š

       1)程序正常退出

       2)使用System.exit()

       3)终端使用Ctrl+C触发的中断

       4)系统关闭

       5)使用Killpid命令杀死进程

       èŽ·å–当前所有ApplicationRunner和CommandLineRunner接口的实现类,执行其run方法

       éåŽ†æ‰€æœ‰çš„SpringApplicationRunListener的finished()方法,完成SpringBoot的启动。

SpringBoot应用启动原理(二)扩展URLClassLoader实现嵌套jar加载

       åœ¨ä¸Šç¯‡æ–‡ç« ã€ŠSpringBoot应用启动原理(一)将启动脚本嵌入jar》中介绍了SpringBoot如何将启动脚本与RunnableJar整合为ExecutableJar的原理,使得生成的jar/war文件可以直接启动

       æœ¬ç¯‡å°†ä»‹ç»SpringBoot如何扩展URLClassLoader实现嵌套jar的类(资源)加载,以启动我们的应用。

       é¦–先,从一个简单的示例开始

       build.gradle

       WebApp.java

       æ‰§è¡Œgradlebuild构建jar包,里面包含应用程序、第三方依赖以及SpringBoot启动程序,其目录结构如下

       æŸ¥çœ‹MANIFEST.MF的内容(MANIFEST.MF文件的作用请自行GOOGLE)

       å¯ä»¥çœ‹åˆ°ï¼Œjar的启动类为org.springframework.boot.loader.JarLauncher,而并不是我们的com.manerfan.SpringBoot.theory.WebApp,应用程序入口类被标记为了Start-Class

       jar启动并不是通过应用程序入口类,而是通过JarLauncher代理启动。其实SpringBoot拥有3中不同的Launcher:JarLauncher、WarLauncher、PropertiesLauncher

       SpringBoot使用Launcher代理启动,其最重要的一点便是可以自定义ClassLoader,以实现对jar文件内(jarinjar)或其他路径下jar、class或资源文件的加载

       å…³äºŽClassLoader的更多介绍可参考《深入理解JVM之ClassLoader》

       SpringBoot抽象了Archive的概念,一个Archive可以是jar(JarFileArchive),可以是一个文件目录(ExplodedArchive),可以抽象为统一访问资源的逻辑层。

       ä¸Šä¾‹ä¸­ï¼Œspring-boot-theory-1.0.0.jar既为一个JarFileArchive,spring-boot-theory-1.0.0.jar!/BOOT-INF/lib下的每一个jar包也是一个JarFileArchive

       å°†spring-boot-theory-1.0.0.jar解压到目录spring-boot-theory-1.0.0,则目录spring-boot-theory-1.0.0为一个ExplodedArchive

       æŒ‰ç…§å®šä¹‰ï¼ŒJarLauncher可以加载内部/BOOT-INF/lib下的jar及/BOOT-INF/classes下的应用class

       å…¶å®žJarLauncher实现很简单

       å…¶ä¸»å…¥å£æ–°å»ºäº†JarLauncher并调用父类Launcher中的launch方法启动程序

       å†åˆ›å»ºJarLauncher时,父类ExecutableArchiveLauncher找到自己所在的jar,并创建archive

       åœ¨Launcher的launch方法中,通过以上archive的getNestedArchives方法找到/BOOT-INF/lib下所有jar及/BOOT-INF/classes目录所对应的archive,通过这些archives的url生成LaunchedURLClassLoader,并将其设置为线程上下文类加载器,启动应用

       è‡³æ­¤ï¼Œæ‰æ‰§è¡Œæˆ‘们应用程序主入口类的main方法,所有应用程序类文件均可通过/BOOT-INF/classes加载,所有依赖的第三方jar均可通过/BOOT-INF/lib加载

       åœ¨åˆ†æžLaunchedURLClassLoader前,首先了解一下URLStreamHandler

       java中定义了URL的概念,并实现多种URL协议(见URL)*/didi/cube-ui。

       cube-ui 从滴滴业务中提炼而来,源码b应用源由滴滴 WebApp 前端架构组开发和维护。启动cube-ui 的源码b应用源目标是让移动端的开发更加容易,让开发人员更加专注于业务逻辑的启动酒楼溯源码燕窝多少钱一克开发,提升研发效率。源码b应用源linux怎么查询源码

       cube-ui 的启动特性包括:精简提炼自滴滴内部组件库,每个组件都有充分单元测试;追求迅速响应、源码b应用源动画流畅、启动接近原生的源码b应用源交互体验;遵循统一的设计交互标准,接口标准化,启动支持按需引入和后编译,源码b应用源轻量灵活;扩展性强,启动交友开发源码可以方便地基于现有组件实现二次开发。源码b应用源

       cube-ui 相对于同类型的启动移动端组件库的优势在于,其组件主要包括基础组件、弹出层组件和滚动组件,台湾新闻直播源码总共开源了 个组件,且在组件的体验和交互,包括易用性上我们都追求极致。cube-ui 支持 2 种使用方式,桌面广告源码声明式和 API 式。

       cube-ui 的某些组件有着很好的扩展性,可以根据实际场景需求做功能的扩展,例如基于弹层类组件的基类开发更丰富的弹层类组件,或者基于移动端选择器组件扩展出城市选择器组件。

       cube-ui 底层依赖了 Vue 和 better-scroll,并依赖了一系列工具做了构建部署、单元测试等工作。未来我们会持续对 cube-ui 迭代和优化,包括但不限于开发更多通用的组件,支持换肤功能,以及考虑对静态类型检查的支持。

copyright © 2016 powered by 皮皮网   sitemap