深入剖析Spring Boot(一)应用搭建和启动
前言
现在后台应用开发中,随着微服务的理念越来越流行,新项目一般都是采用SpringBoot快速搭建,无需之前复杂的xml配置,一个注解,几行代码,程序完全能正常运行。Convertion over Configuration 也是应用开发中的一个趋势,通过对Spring和SpringBoot的学习,打算把自己的一些理解和心得记录下来,写成一个系列,与其说叫SpringBoot深入剖析,不如说Spring深入剖析,SpringBoot只是对Spring的一小部分扩展,通过自动化配置取代了之前xml的配置形式,后续分析中可以很明确发现这一点。
Spring Boot 应用
一般来说,SpringBoot应用一般长这个样子:
@SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
在配上一个Controller,一个最简单的应用就搭建完成;当然SpringBoot还提供了一种可以对Application进一步扩展的方式:SpringApplicationBuilder
@SpringBootApplication public class Application { public static void main(String[] args) { new SpringApplicationBuilder() .sources(Parent.class) .child(Application.class) .bannerMode(Banner.Mode.OFF) .run(args); } }
这还不算完,你仍然可以进一步扩展,SpringApplicationBuilder内部实现来看是新建了一个SpringApplication,然后设置一系列的属性,那么我们是否可以继承SpringApplication来实现更多的扩展需求,答案是肯定的。SpringBoot的注释也明确说明(我一直觉得很多优秀的开源框架注释非常值得一读)。
SpringApplicationBuilder 中createSpringApplication方法中,使用了protected关键字(对Sping这个极讲究的框架而言,这个关键字几乎说明了是可扩展的)并且说明子类可以覆盖并生成自定义的SpringApplication,下面是个简单的例子来说明如何自定义我们的Application:
@SpringBootApplication public class MyApplication extends SpringApplication { public MyApplication() { } public MyApplication(Class<?>... primarySources) { super(primarySources); } @Override protected ConfigurableApplicationContext createApplicationContext() { return super.createApplicationContext(); } public static class MyApplicationBuilder extends SpringApplicationBuilder{ public MyApplicationBuilder() { super(MyApplication.class); this.bannerMode(Banner.Mode.OFF); } @Override protected SpringApplication createSpringApplication(Class<?>... sources) { return new MyApplication(sources); } } public static void main(String[] args) { new MyApplication.MyApplicationBuilder().run(args); } }
例子中只是简单的扩展,通过重写createApplicationContext()方法我们可以实现自己特殊需求的应用上下文,SpringApplication提供的扩展有很多,感兴趣的话可以点进去根据不同需求做进一步扩展。
启动原理
理解SpringBoot应用的构建后,我们看到启动的起点是SpringApplication的run()方法,先忽略掉部分无关大局的细节代码,启动过程最关键的两步是:
context = createApplicationContext(); refreshContext(context);
这里可以停下简单回想在SpringBoot以前应用是如何创建ApplicationContext的,正常来说我们会在web.xml中配置DispatcherServlet:
<listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/applicationContext.xml</param-value> </context-param> <servlet> <servlet-name>dispatch</servlet> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/dispatcherServlet.xml</param-value> </init-param>
配置的listener 会在容器启动时创建Root 上下文,然后会初始化DispatchServlet,在initServletBean()时创建web应用上下文;在SpringBoot中,servlet容器是内置的,在程序启动时容器还并未初始化。SpringBoot通过简单的判断应用环境决定创建的上下文环境:
switch(this.webApplicationType) { case SERVLET: ontextClass = Class.forName("org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext"); break; case REACTIVE: contextClass = Class.forName("org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext"); break; default: contextClass = Class.forName("org.springframework.context.annotation.AnnotationConfigApplicationContext"); }
webApplicationType 的判断是在classPath中寻找特定的类,在导入springmvc的依赖后,SpringApplication找到”javax.servlet.Servlet”,
“org.springframework.web.context.ConfigurableWebApplicationContext”,判定为Servlet Web应用,于是会创建AnnotationConfigServletWebServerApplicationContext,有了ApplicationContext,接下来就是刷新了:
protected void refresh(ApplicationContext applicationContext) { Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext); ((AbstractApplicationContext) applicationContext).refresh(); }
我们看到,最终还是到了可以说是Spring最核心的refresh模板方法,这些方法中,不同的Applicatcontext实现上有很大的差别,举个例子:SpringBoot应用一般是纯注解的,那么在refreshBeanFactory() 方法中,它是不会做事情的,相反XmlClassPathApplicationContext中关于xml配置的解析都是在这里完成的。
本篇就到这里,后续会详细讲解SpringBoot的上下文是如何实现各个模板方法的以及和常规实现的一些区别;
总结
通过对Spring应用创建和启动的初步分析,我们可以看到,SpringBoot其实是简单的一层壳子,是基于Spring通过自动化配置简化了之前复杂的配置文件,使得程序员上手和开发更加方便,高效。
阅读更多- 【深入SpringBoot 1.3.5 第一章】Boot应用的启动流程
- [深入剖析Spring Boot]启动、事件通知与配置加载原理
- 【深入SpringBoot 1.3.5 第一章】Boot应用的启动流程
- 深入JVM分析spring-boot应用hibernate-validator
- spring boot应用启动原理分析
- 用Spring Boot & Cloud,Angular2快速搭建微服务web应用 - 实现RESTful CRUD
- SpringBoot应用启动过程分析
- Spring Boot应用启动原理分析(转)
- 使用Overcast搭建spring boot应用集成测试环境
- SpringBoot项目Web应用搭建
- 聊聊SpringBoot | 第一章:快速搭建SpringBoot第一个应用
- Spring boot应用启动原理分析
- spring boot应用启动原理分析
- Spring Boot的应用正常启动与关闭
- spring boot应用启动原理分析
- 004-Spring boot 快速入门-项目搭建与启动、SpringBootApplication
- 深入理解Spring 之 源码剖析 SpringBoot Aop 切面编织过程和代理执行过程
- spring boot应用启动原理分析
- 【SpringBoot】2.快速搭建一个SpringBoot应用
- SpringBoot应用启动流程