深入剖析Spring Boot(一)应用搭建和启动

扫码关注公众号:Java 技术驿站

发送:vip
将链接复制到本浏览器,永久解锁本站全部文章

【公众号:Java 技术驿站】 【加作者微信交流技术,拉技术群】

前言

现在后台应用开发中,随着微服务的理念越来越流行,新项目一般都是采用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通过自动化配置简化了之前复杂的配置文件,使得程序员上手和开发更加方便,高效。


来源:http://ddrv.cn

赞(0) 打赏
版权归原创作者所有,任何形式的转载请联系博主:daming_90:Java 技术驿站 » 深入剖析Spring Boot(一)应用搭建和启动

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏