原文自工程师 baeldung 博客, 传送门
最近到了春招的时间, 各位同学们都开始努力准备面试相关的事项, 这边 Eugen 老师在 baeldung 中发表了一篇和 SpringBoot 相关的面试题目以及解答, 希望对大家有帮助.
概述
从诞生那天开始, SpringBoot 就在 Spring 生态中扮演一个重要的地位. 这个项目的自动化部署功能使我们的编程工作变得更方便.
在这篇文章当中, 我们将介绍一些在工程师面试中可能会出现的 Spring Boot 相关的常见问题.
问题
Q1. Spring 和 SpringBoot 有什么不同?
Spring 框架提供多种特性使得 web 应用开发变得更简便, 包括依赖注入, 数据绑定, 切面编程, 数据存取等等.
随着时间推移, Spring 生态变得越来越复杂了, 并且应用程序所必须的配置文件也令人觉得可怕. 这就是 Spirng Boot 派上用场的地方了 - 它使得 Spring 的配置变得更轻而易举.
实际上, Spring 是 unopinionated(予以配置项多, 倾向性弱) 的, Spring Boot 在平台和库的做法中更 opinionated , 使得我们更容易上手.
这里有两条 SpringBoot 带来的好处:
根据 classpath 中的 artifacts 的自动化配置应用程序
提供非功能性特性例如安全和健康检查给到生产环境中的应用程序
Q2. 怎么使用 Maven 来构建一个 SpringBoot 程序?
就像引入其他库一样, 我们可以在 Maven 工程中加入 SpringBoot 依赖. 然而, 最好是从 spring-boot-starter-parent 项目中继承以及声明依赖到 Spring Boot starters. 这样做可以使我们的项目可以重用 SpringBoot 的默认配置.
继承 spring-boot-starter-parent 项目依赖很简单 - 我们只需要在 pom.xml 中定义一个 parent 节点:
- <parent>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-parent</artifactId>
- <version>2.1.1.RELEASE</version>
- </parent>
我们可以在 Maven central 中找到 spring-boot-starter-parent 的最新版本.
使用 starter 父项目依赖很方便, 但并非总是可行. 例如, 如果我们公司都要求项目继承标准 POM, 我们就不能依赖 SpringBoot starter 了.
这种情况, 我们可以通过对 POM 元素的依赖管理来处理:
- <dependencyManagement>
- <dependencies>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-dependencies</artifactId>
- <version>2.1.1.RELEASE</version>
- <type>pom</type>
- <scope>import</scope>
- </dependency>
- </dependencies>
- </dependencyManagement>
最后, 我们可以添加 SpringBoot starter 中一些依赖, 然后我们就可以开始了.
Q3. SpringBoot starter 作用在什么地方?
依赖管理是所有项目中至关重要的一部分. 当一个项目变得相当复杂, 管理依赖会成为一个噩梦, 因为当中涉及太多 artifacts 了.
这时候 SpringBoot starter 就派上用处了. 每一个 stater 都在扮演着提供我们所需的 Spring 特性的一站式商店角色. 其他所需的依赖以一致的方式注入并且被管理.
所有的 starter 都归于 org.springframework.boot 组中, 并且它们都以由 spring-boot-starter- 开头取名. 这种命名方式使得我们更容易找到 starter 依赖, 特别是当我们使用那些支持通过名字查找依赖的 IDE 当中.
在写这篇文章的时候, 已经有超过 50 个 starter 了, 其中最常用的是:
spring-boot-starter: 核心 starter, 包括自动化配置支持, 日志以及 YAML
spring-boot-starter-aop:Spring AOP 和 AspectJ 相关的切面编程 starter
spring-boot-starter-data-jpa: 使用 Hibernate Spring Data JPA 的 starter
spring-boot-starter-jdbc: 使用 HikariCP 连接池 JDBC 的 starter
spring-boot-starter-security: 使用 Spring Security 的 starter
spring-boot-starter-test:SpringBoot 测试相关的 starter
spring-boot-starter-Web: 构建 restful,springMVC 的 Web 应用程序的 starter
Q4. 怎么禁用某些自动配置特性?
如果我们想禁用某些自动配置特性, 可以使用 @EnableAutoConfiguration 注解的 exclude 属性来指明. 例如, 下面的代码段是使 DataSourceAutoConfiguration 无效:
- // other annotations
- @EnableAutoConfiguration(exclude = DataSourceAutoConfiguration.class)
- public class MyConfiguration {
- }
如果我们使用 @SpringBootApplication 注解 - 那个将 @EnableAutoConfiguration 作为元注解的项, 来启用自动化配置, 我们能够使用相同名字的属性来禁用自动化配置:
- // other annotations
- @SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
- public class MyConfiguration {
- }
我们也能够使用 spring.autoconfigure.exclude 环境属性来禁用自动化配置. application.properties 中的这项配置能够像以前那样做同样的事情:
spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
Q5. 怎么注册一个定制的自动化配置?
为了注册一个自动化配置类, 我们必须在 META-INF/spring.factories 文件中的 EnableAutoConfiguration 键下列出它的全限定名:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.baeldung.autoconfigure.CustomAutoConfiguration
如果我们使用 Maven 构建项目, 这个文件需要放置在在 package 阶段被写入完成的 resources/META-INF 目录中.
Q6. 当 bean 存在的时候怎么置后执行自动配置?
为了当 bean 已存在的时候通知自动配置类置后执行, 我们可以使用 @ConditionalOnMissingBean 注解. 这个注解中最值得注意的属性是:
value: 被检查的 beans 的类型
name: 被检查的 beans 的名字
当将 @Bean 修饰到方法时, 目标类型默认为方法的返回类型:
- @Configuration
- public class CustomConfiguration {
- @Bean
- @ConditionalOnMissingBean
- public CustomService service() { ... }
- }
Q7. 怎么将 SpringBoot Web 应用程序部署为 JAR 或 WAR 文件?
通常, 我们将 Web 应用程序打包成 WAR 文件, 然后将它部署到另外的服务器上. 这样做使得我们能够在相同的服务器上处理多个项目. 当 CPU 和内存有限的情况下, 这是一种最好的方法来节省资源.
然而, 事情发生了转变. 现在的计算机硬件相比起来已经很便宜了, 并且现在的注意力大多转移到服务器配置上. 部署中对服务器配置的一个细小的失误都会导致无可预料的灾难发生.
Spring 通过提供插件来解决这个问题, 也就是 spring-boot-maven-plugin 来打包 Web 应用程序到一个额外的 JAR 文件当中. 为了引入这个插件, 只需要在 pom.xml 中添加一个 plugin 属性:
- <plugin>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-maven-plugin</artifactId>
- </plugin>
有了这个插件, 我们会在执行 package 步骤后得到一个 JAR 包. 这个 JAR 包包含所需的所有依赖以及一个嵌入的服务器. 因此, 我们不再需要担心去配置一个额外的服务器了.
我们能够通过运行一个普通的 JAR 包来启动应用程序.
注意一点, 为了打包成 JAR 文件, pom.xml 中的 packgaing 属性必须定义为 jar:
<packaging>jar</packaging>
如果我们不定义这个元素, 它的默认值也为 jar.
如果我们想构建一个 WAR 文件, 将 packaging 元素修改为 war:
<packaging>war</packaging>
并且将容器依赖从打包文件中移除:
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-tomcat</artifactId>
- <scope>provided</scope>
- </dependency>
执行 Maven 的 package 步骤之后, 我们得到一个可部署的 WAR 文件.
Q8. 怎么使用 SpringBoot 去执行命令行程序?
像其他 Java 程序一样, 一个 SpringBoot 命令行程序必须要有一个 main 方法. 这个方法作为一个入口点, 通过调用 SpringApplication#run 方法来驱动程序执行:
- @SpringBootApplication
- public class MyApplication {
- public static void main(String[] args) {
- SpringApplication.run(MyApplication.class);
- // other statements
- }
- }
SpringApplication 类会启动一个 Spirng 容器以及自动化配置 beans.
要注意的是我们必须把一个配置类传递到 run 方法中作为首要配置资源. 按照惯例, 这个参数一般是入口类本身.
在调用 run 方法之后, 我们可以像平常的程序一样执行其他语句.
Q9. 有什么外部配置的可能来源?
SpringBoot 对外部配置提供了支持, 允许我们在不同环境中运行相同的应用. 我们可以使用 properties 文件, YAML 文件, 环境变量, 系统参数和命令行选项参数来声明配置属性.
然后我们可以通过 @Value 这个通过 @ConfigurationProperties 绑定的对象的注解或者实现 Enviroment 来访问这些属性.
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-devtools</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-actuator</artifactId>
- </dependency>
来源: https://juejin.im/post/5c749aebe51d45163461b166