美文网首页
spring boot简介

spring boot简介

作者: 骚黑 | 来源:发表于2020-10-15 02:21 被阅读0次

    一、什么是Spring Boot?

    Spring Boot是由pivotal团队所提供,目的是为了简化Spring应用的初始化搭建以及开发过程。
    先以最基础的Spring Mvc项目为例,通过是否使用Spring Boot搭建项目,对比下差异。

    二、Spring Boot使用

    2.1不使用Spring Boot项目搭建

    创建一个Spring Mvc Maven项目需要以下几步
    1:创建一个Maven Web项目
    2:pom.xml引入相关依赖

    <dependencies>
                <dependency>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-context</artifactId>
                    <version>${spring.version}</version>
                </dependency>
    
                <dependency>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-web</artifactId>
                    <version>${spring.version}</version>
                </dependency>
    
                <dependency>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-webmvc</artifactId>
                    <version>${spring.version}</version>
                </dependency>
    
                <dependency>
                    <groupId>javax.servlet</groupId>
                    <artifactId>servlet-api</artifactId>
                    <version>2.5</version>
                    <scope>provided</scope>
                </dependency>
    
                <dependency>
                    <groupId>javax.servlet.jsp</groupId>
                    <artifactId>jsp-api</artifactId>
                    <version>2.0</version>
                    <scope>provided</scope>
                </dependency>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.11</version>
                <scope>test</scope>
            </dependency>
        </dependencies>
    

    3.在web.xml中配置SpringMvc核心控制器DispatcherServlet

    <!DOCTYPE web-app PUBLIC
     "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
     "http://java.sun.com/dtd/web-app_2_3.dtd" >
    
    <web-app>
      <display-name>Archetype Created Web Application</display-name>
      <!-- SpringMVC的核心控制器 -->
      <servlet>
        <servlet-name>dispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- 配置Servlet的初始化参数,读取springmvc的配置文件,创建spring容器 -->
        <init-param>
          <param-name>contextConfigLocation</param-name>
          <param-value>classpath:springMvc.xml</param-value>
        </init-param>
        <!-- 配置servlet启动时加载对象 -->
        <load-on-startup>1</load-on-startup>
      </servlet>
      
      <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
      </servlet-mapping>
    </web-app>
    
    

    4.配置SpringMvc相关配置

    <!DOCTYPE web-app PUBLIC
     "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
     "http://java.sun.com/dtd/web-app_2_3.dtd" >
    
    <web-app>
      <display-name>Archetype Created Web Application</display-name>
      <!-- SpringMVC的核心控制器 -->
      <servlet>
        <servlet-name>dispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- 配置Servlet的初始化参数,读取springmvc的配置文件,创建spring容器 -->
        <init-param>
          <param-name>contextConfigLocation</param-name>
          <param-value>classpath:springMvc.xml</param-value>
        </init-param>
        <!-- 配置servlet启动时加载对象 -->
        <load-on-startup>1</load-on-startup>
      </servlet>
      
      <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
      </servlet-mapping>
    </web-app>
    
    

    5.编写Controller代码
    6.部署启动tomcat容器

    2.1使用Spring Boot项目搭建

    创建一个Spring Boot Web Maven项目需要以下几步
    1:创建一个继承spring-boot-starter-parent的Maven项目

          <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.3.4.RELEASE</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
    

    2:引入spring-boot-starter依赖

    <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
                <exclusions>
                    <exclusion>
                        <groupId>org.junit.vintage</groupId>
                        <artifactId>junit-vintage-engine</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
        </dependencies>
    

    3:创建启动类

      @SpringBootApplication
      public class SpringBootWebApplication {
        public static void main(String[] args) throws IOException {
            SpringApplication.run(SpringBootWebApplication.class, args);
        }
      }
    

    4:编写Controller代码
    5:运行启动类
    对比一下,spring boot创建项目确实简单许多。

    三、Spring Boot如何实现

    官方给出Spring Boot的特征 :

    1. 创建独立的Spring applications
    2. 嵌入tomcat,jetty,Undertow(无需部署WAR文件)
    3. 提供基础依赖项,简化构建
    4. 尽可能自动配置spring和第三方库
    5. 提供可用于生产的功能,例如指标、运行状况检查、和外部化配置
    6. 完全没有代码生成、也不需要XML配置

    除了第5点(本文不涉及),其它都很清晰。结合Spring Boot的目的,可以看出Spring Boot是通过提供基础依赖自动配置内嵌服务器三个方面来实现“简化Spring应用的初始化搭建以及开发过程”这一目的。

    3.1基础依赖提供###

    通过查看Spring Boot项目中引入的spring-boot-starter-web依赖不难发现,Spring Boot利用maven(Gradle相同)依赖具有传递性的特点,通过引入spring-boot-starter-web依赖,间接引入了spring Mvc相关依赖。实际上通过阅读Spring Boot源码不难发现spring-boot-starter-xxx项目下都没有java代码,而仅包含pom.xml文件。各pom.xml文件中配置对应Spring xxx应用所需依赖。
    注:由于Spring boot2.3.0之后使用Gradle构建,所以本文Spring Boot项目源码版本为2.2
    查看spring-boot-starter-web源码中pom.xml文件如下:

    <dependencies>
      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
        <version>2.3.4.RELEASE</version>
        <scope>compile</scope>
      </dependency>
      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-json</artifactId>
        <version>2.3.4.RELEASE</version>
        <scope>compile</scope>
      </dependency>
      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-tomcat</artifactId>
        <version>2.3.4.RELEASE</version>
        <scope>compile</scope>
      </dependency>
      <!--看这里,引入了Spring Mvc的相关依赖-->
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
        <version>5.2.9.RELEASE</version>
        <scope>compile</scope>
      </dependency>
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.2.9.RELEASE</version>
        <scope>compile</scope>
      </dependency>
    </dependencies>
    

    3.2自动配置

    了解Spring Boot自动配置之前,需要先了解Spring Spi机制(详情可以百度)。简单来说就是在项目META-INF/spring.factories文件中配置接口的实现类名称,然后在程序中读取这些配置文件并实例化。
    Spring Boot自动配置的关键是启动类上注解@SpringBootApplication和SpringApplication.run(SpringBootWebApplication.class, args)
    首先查看@SpringBootApplication源码如下

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    @SpringBootConfiguration
    @EnableAutoConfiguration
    @ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
            @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
    public @interface SpringBootApplication
    

    @SpringBootApplication是一个组合注解,主要关注

    • @ComponentScan注解很熟悉,自动扫描组件。
    • @EnableAutoConfiguration注解源码如下
      @Target(ElementType.TYPE)
      @Retention(RetentionPolicy.RUNTIME)
      @Documented
      @Inherited
      @AutoConfigurationPackage
      @Import(AutoConfigurationImportSelector.class)
      public @interface EnableAutoConfiguration 
      

    @EnableAutoConfiguration注解包含 @Import(AutoConfigurationImportSelector.class)。
    跟踪AutoConfigurationImportSelector代码可以看到getAutoConfigurationEntry方法使用Spring Spi获取类加载器内META-INF/spring.factories配置文件中的EnableAutoConfiguration的配置。

    protected AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata,AnnotationMetadata annotationMetadata) {
            if (!isEnabled(annotationMetadata)) {
                return EMPTY_ENTRY;
            }
            AnnotationAttributes attributes = getAttributes(annotationMetadata);
            //此行代码获取配置文件中的EnableAutoConfiguration加载类名
            List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
            configurations = removeDuplicates(configurations);
            Set<String> exclusions = getExclusions(annotationMetadata, attributes);
            checkExcludedClasses(configurations, exclusions);
            configurations.removeAll(exclusions);
            configurations = filter(configurations, autoConfigurationMetadata);
            fireAutoConfigurationImportEvents(configurations, exclusions);
            return new AutoConfigurationEntry(configurations, exclusions);
        }
    

    跟踪启动类SpringApplication.run(SpringBootWebApplication.class, args)代码,run方法中通过refreshContext(context)调用AutoConfigurationImportSelector.getAutoConfigurationEntry方法加载需要自动配置的类

    public ConfigurableApplicationContext run(String... args) {
            StopWatch stopWatch = new StopWatch();
            stopWatch.start();
            ConfigurableApplicationContext context = null;
            Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
            configureHeadlessProperty();
            SpringApplicationRunListeners listeners = getRunListeners(args);
            listeners.starting();
            try {
                ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
                ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
                configureIgnoreBeanInfo(environment);
                Banner printedBanner = printBanner(environment);
                context = createApplicationContext();
                exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
                        new Class[] { ConfigurableApplicationContext.class }, context);
                prepareContext(context, environment, listeners, applicationArguments, printedBanner);
                //此行代码调用AutoConfigurationImportSelector.getAutoConfigurationEntry方法         
                refreshContext(context);
                afterRefresh(context, applicationArguments);
                stopWatch.stop();
                if (this.logStartupInfo) {
                    new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
                }
                listeners.started(context);
                callRunners(context, applicationArguments);
            }
            catch (Throwable ex) {
                handleRunFailure(context, ex, exceptionReporters, listeners);
                throw new IllegalStateException(ex);
            }
    
            try {
                listeners.running(context);
            }
            catch (Throwable ex) {
                handleRunFailure(context, ex, exceptionReporters, null);
                throw new IllegalStateException(ex);
            }
            return context;
        }
    

    META-INF/spring.factories EnableAutoConfiguration配置中包含Spring Boot整合所有Spring应用的自动配置类,Spring Boot如何区分应该加载哪些应用自动配置类呢?查看EnableAutoConfiguration中Spring Mvc自动配置类WebMvcAutoConfiguration,源码如下

    @Configuration(proxyBeanMethods = false)
    //当前是否为servlet web应用
    @ConditionalOnWebApplication(type = Type.SERVLET)
    //当前classpath上是否包含Servlet、DispatcherServlet、WebMvcConfigurer三个类
    @ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
    //上下文中不存在WebMvcConfigurationSupport对象
    @ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
    @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
    @AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class,
            ValidationAutoConfiguration.class })
    public class WebMvcAutoConfiguration 
    

    WebMvcAutoConfiguration 类中包含3个@ConditionalOnxxx。Spring Boot通过@ConditionalOnxxx区分当前配置类是否应该被加载,当所有@ConditionalOnxxx为真时,配置类才被加载。完整@ConditionalOnxxx请查看

    3.3内嵌服务器

    三、总结

    Spring Boot极大的简化了Spring应用的开发。对于Spring Boot基本原理做了基本了解,对于各自动配置内容,Spring Boot细节还需通过阅读源码、文档深入学习。

    参考

    相关文章

      网友评论

          本文标题:spring boot简介

          本文链接:https://www.haomeiwen.com/subject/wfzipktx.html