Spring Boot是什么?Spring Boot应用

白昊东
2023-12-01

  Spring Boot 去除了大量的 xml 配置文件,简化了复杂的依赖管理, 配合各种 starter 使用,基本上可以做到自动化配置。Spring 可以做的事情,现在用 Spring boot 都可以做。

1、Spring Boot 核心功能

  1. 独立运行的 Spring 项目

    Spring Boot 可以以 jar 包的形式独立运行,运行一个 Spring Boot 项目只需通过 java–jar xx.jar 来运行。

  2. 内嵌 Servlet 容器

    Spring Boot 可选择内嵌 Tomcat、Jetty 或者 Undertow,这样我们无须以 war 包形式部署项目。

  3. 提供 starter 简化 Maven 配置

    Spring 提供了一系列的 starter pom 来简化 Maven 的依赖加载

  4. 自动配置 Spring

    Spring Boot 会根据在类路径中的 jar 包、类,为 jar 包里的类自动配置 Bean,这样会极大地减少我们要使用的配置。当然,Spring Boot 只是考虑了大多数的开发场景,并不是所有的场景,若在实际开发中我们需要自动配置 Bean,而 Spring Boot 没有提供支持,则可以自定义自动配置。

  5. 准生产的应用监控

    Spring Boot 提供基于 http、ssh、telnet 对运行时的项目进行监控。

  6. 无代码生成和 xml 配置

    Spring Boot 的神奇的不是借助于代码生成来实现的,而是通过条件注解来实现的,这是 Spring 4.x 提供的新特性。Spring 4.x 提倡使用 Java 配置和注解配置组合,而 Spring Boot 不需要任何 xml 配置即可实现 Spring 的所有配置。

2、Spring Boot的优缺点

  1. 优点
    • 快速构建项目。
    • 对主流开发框架的无配置集成。
    • 项目可独立运行,无须外部依赖Servlet容器。
    • 提供运行时的应用监控。
    • 极大地提高了开发、部署效率。
    • 与云计算的天然集成。
  2. 缺点
    • 版本迭代速度很快,一些模块改动很大。
    • 由于不用自己做配置,报错时很难定位。
    • 网上现成的解决方案比较少。

3、Spring IoC介绍

  IoC 其实有两种方式,一种就是 DI,而另一种是 DL,即 Dependency Lookup(依赖查找),前者是当前软件实体被动接受其依赖的其他组件被 IoC 容器注入,而后者则是当前软件实体主动去某个服务注册地查找其依赖的那些服务.

  Spring 框架提供的 IoC 容器实现(IoC Container),而使用 Spring IoC 容器的一个典型代码片段就是:

public class App {
    public static void main(String[] args) {
        ApplicationContext context = new FileSystemXmlApplication-Context("...");
        // ...
        MockService service = context.getBean(MockService.class);
        service.doSomething();
    }
}

Spring IoC 容器的依赖注入工作可以分为两个阶段:

1、收集和注册

  第一个阶段可以认为是构建和收集 bean 定义的阶段,在这个阶段中,我们可以通过 XML 或者 Java 代码的方式定义一些 bean,然后通过手动组装或者让容器基于某些机制自动扫描的形式,将这些 bean 定义收集到 IoC 容器中。

  假设我们以 XML 配置的形式来收集并注册单一 bean,一般形式如下:

<bean id="mockService" class="..MockServiceImpl"> ...</bean>

  如果嫌逐个收集 bean 定义麻烦,想批量地收集并注册到 IoC 容器中,我们也可以通过 XML Schema 形式的配置进行批量扫描并采集和注册:

<context:component-scan base-package="com.keevol">

  注意基于 JavaConfig 形式的收集和注册,不管是单一还是批量,后面我们都会单独提及。

2、分析和组装

  当第一阶段工作完成后,我们可以先暂且认为 IoC 容器中充斥着一个个独立的 bean,它们之间没有任何关系。

  但实际上,它们之间是有依赖关系的,所以,IoC 容器在第二阶段要干的事情就是分析这些已经在 IoC 容器之中的 bean,然后根据它们之间的依赖关系先后组装它们。

  如果 IoC 容器发现某个 bean 依赖另一个 bean,它就会将这另一个 bean 注入给依赖它的那个 bean,直到所有 bean 的依赖都注入完成,所有 bean 都“整装待发”,整个 IoC 容器的工作即算完成。

  至于分析和组装的依据,Spring 框架最早是通过 XML 配置文件的形式来描述 bean 与 bean 之间的关系的,随着 Java 业界研发技术和理念的转变,基于 Java 代码和 Annotation 元信息的描述方式也日渐兴盛(比如 @Autowired 和 @Inject),但不管使用哪种方式,都只是为了简化绑定逻辑描述的各种“表象”,最终都是为本阶段的最终目的服务。

  很多 Java 开发者一定认为 Spring 的 XML 配置文件是一种配置(Configuration),但本质上,这些配置文件更应该是一种代码形式,XML 在这里其实可以看作一种 DSL,它用来表述的是 bean 与 bean 之间的依赖绑定关系,如果没有 IoC 容器就要自己写代码新建(new)对象并配置(set)依赖。

4、Spring Boot快速搭建

  我们说 SpringBoot 是 Spring 框架对“约定优先于配置(Convention Over Configuration)”理念的最佳实践的产物,一个典型的 SpringBoot 应用本质上其实就是一个基于 Spring 框架的应用

  一般情况下,我们会得到一个 SpringBoot 应用的启动类,如下面代码所示:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

5、SpringBoot中@SpringBootApplication注解的三体结构解析

@SpringBootApplication 是一个“三体”结构,实际上它是一个复合 Annotation:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Configuration
@EnableAutoConfiguration
@ComponentScanpublic
@interface
SpringBootApplication{...}

虽然它的定义使用了多个 Annotation 进行元信息标注,但实际上对于 SpringBoot 应用来说,重要的只有三个 Annotation,而“三体”结构实际上指的就是这三个 Annotation:

@Configuration
@EnableAutoConfiguration
@ComponentScan

所以,如果我们使用如下的 SpringBoot 启动类,整个 SpringBoot 应用依然可以与之前的启动类功能对等:

@Configuration
@EnableAutoConfiguration
@ComponentScanpublic
class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

但每次都写三个 Annotation 显然过于繁琐,所以写一个 @SpringBootApplication 这样的一站式复合 Annotation 显然更方便些。

5.1、@Configuration

  很多 SpringBoot 的代码示例都喜欢在启动类上直接标注 @Configuration 或者 @SpringBootApplication,对于初接触 SpringBoot 的开发者来说,其实这种做法不便于理解,如果我们将上面的 SpringBoot 启动类拆分为两个独立的 Java 类,整个形势就明朗了:

@Configuration
@EnableAutoConfiguration
@ComponentScan
public class DemoConfiguration {
    @Bean
    public Controller controller() {
        return new Controller();
    }
}

public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoConfiguration.class, args);
    }
}

  所以,启动类 DemoApplication 其实就是一个标准的 Standalone 类型 Java 程序的 main 函数启动类,没有什么特殊的。而 @Configuration 标注的 DemoConfiguration 定义其实也是一个普通的 JavaConfig 形式的 IoC 容器配置类。

5.2、@EnableAutoConfiguration

  @EnableAutoConfiguration 其实也没啥“创意”,各位是否还记得 Spring 框架提供的各种名字为 @Enable 开头的 Annotation 定义?

  比如 @EnableScheduling、@EnableCaching、@EnableMBeanExport 等,@EnableAutoConfiguration 的理念和“做事方式”其实一脉相承,简单概括一下就是,借助 @Import 的支持,收集和注册特定场景相关的 bean 定义:
@EnableScheduling 是通过 @Import 将 Spring 调度框架相关的 bean 定义都加载到 IoC 容器。
@EnableMBeanExport 是通过 @Import 将 JMX 相关的 bean 定义加载到 IoC 容器。

  而 @EnableAutoConfiguration 也是借助 @Import 的帮助,将所有符合自动配置条件的 bean 定义加载到 IoC 容器,仅此而已!

@EnableAutoConfiguration 作为一个复合 Annotation,其自身定义关键信息如下:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(EnableAutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {...}

  其中,最关键的要属 @Import(EnableAutoConfigurationImportSelector.class),借助 EnableAutoConfigurationImportSelector,@EnableAutoConfiguration 可以帮助 SpringBoot 应用将所有符合条件的 @Configuration 配置都加载到当前 SpringBoot 创建并使用的 IoC 容器。

5.3、@ComponentScan

  原则上来说,作为 Spring 框架里的“老一辈革命家”,@ComponentScan 的功能其实就是自动扫描并加载符合条件的组件或 bean 定义,最终将这些 bean 定义加载到容器中。加载 bean 定义到 Spring 的 IoC 容器,我们可以手工单个注册,不一定非要通过批量的自动扫描完成,所以说 @ComponentScan 是可有可无的。

  对于 SpringBoot 应用来说,同样如此,比如我们本章的启动类:

@Configuration
@EnableAutoConfiguration
@ComponentScanpublic
class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

  如果我们当前应用没有任何 bean 定义需要通过 @ComponentScan 加载到当前 SpringBoot 应用对应使用的 IoC 容器,那么,除去 @ComponentScan 的声明,当前 SpringBoot 应用依然可以照常运行,功能对等。

后续待增加

 类似资料: