精尽 Spring Boot 面试题
以下面试题,基于网络整理,和自己编辑。具体参考的文章,会在文末给出所有的链接。
如果胖友有自己的疑问,欢迎在星球提问,我们一起整理吊吊的 Spring Boot 面试题的大保健。
而题目的难度,艿艿尽量按照从容易到困难的顺序,逐步下去。
在内容上,我们会分成两大块:
核心技术篇,分享 Spring Boot 的核心技术相关的内容。
整合篇,分享 Spring Boot 整合一些框架的面试题,例如 JPA 如何集成到 Spring Boot 中。
核心技术篇
Spring Boot 是什么?
Spring Boot 是 Spring 的子项目,正如其名字,提供 Spring 的引导( Boot )的功能。
通过 Spring Boot ,我们开发者可以快速配置 Spring 项目,引入各种 Spring MVC、Spring Transaction、Spring AOP、MyBatis 等等框架,而无需不断重复编写繁重的 Spring 配置,降低了 Spring 的使用成本。
艿艿:犹记当年,Spring XML 为主的时代,大晚上各种搜索 Spring 的配置,苦不堪言。现在有了 Spring Boot 之后,生活真美好。
Spring Boot 提供了各种 Starter 启动器,提供标准化的默认配置。例如:
spring-boot-starter-web 启动器,可以快速配置 Spring MVC 。
mybatis-spring-boot-starter 启动器,可以快速配置 MyBatis 。
并且,Spring Boot 基本已经一统 Java 项目的开发,大量的开源项目都实现了其的 Starter 启动器。例如:
incubator-dubbo-spring-boot-project 启动器,可以快速配置 Dubbo 。
rocketmq-spring-boot-starter 启动器,可以快速配置 RocketMQ 。
Spring Boot 提供了哪些核心功能?
1、独立运行 Spring 项目
Spring Boot 可以以 jar 包形式独立运行,运行一个 Spring Boot 项目只需要通过 java -jar xx.jar 来运行。
2、内嵌 Servlet 容器
Spring Boot 可以选择内嵌 Tomcat、Jetty 或者 Undertow,这样我们无须以 war 包形式部署项目。
第 2 点是对第 1 点的补充,在 Spring Boot 未出来的时候,大多数 Web 项目,是打包成 war 包,部署到 Tomcat、Jetty 等容器。
3、提供 Starter 简化 Maven 配置
Spring 提供了一系列的 starter pom 来简化 Maven 的依赖加载。例如,当你使用了 spring-boot-starter-web ,会自动加入如下依赖:
4、自动配置 Spring Bean
Spring Boot 检测到特定类的存在,就会针对这个应用做一定的配置,进行自动配置 Bean ,这样会极大地减少我们要使用的配置。
当然,Spring Boot 只考虑大多数的开发场景,并不是所有的场景,若在实际开发中我们需要配置Bean ,而 Spring Boot 没有提供支持,则可以自定义自动配置进行解决。
5、准生产的应用监控
Spring Boot 提供基于 HTTP、JMX、SSH 对运行时的项目进行监控。
6、无代码生成和 XML 配置
Spring Boot 没有引入任何形式的代码生成,它是使用的 Spring 4.0 的条件 @Condition 注解以实现根据条件进行配置。同时使用了 Maven /Gradle 的依赖传递解析机制来实现 Spring 应用里面的自动配置。
第 6 点是第 3 点的补充。
Spring Boot 有什么优缺点?
艿艿:任何技术栈,有优点必有缺点,没有银弹。
另外,这个问题的回答,我们是基于 《Spring Boot浅谈(是什么/能干什么/优点和不足)》 整理,所以胖友主要看下这篇文章。
Spring Boot 的优点
艿艿:优点和 「Spring Boot 提供了哪些核心功能?」 问题的答案,是比较重叠的。
1、使【编码】变简单。
2、使【配置】变简单。
3、使【部署】变简单。
4、使【监控】变简单。
Spring Boot 的缺点
艿艿:如下的缺点,基于 《Spring Boot浅谈(是什么/能干什么/优点和不足)》,考虑的出发点是把 Spring Boot 作为微服务的框架的选型的角度进行考虑。
1、没有提供相应的【服务发现和注册】的配套功能。
艿艿:当然,实际上 Spring Boot 本身是不需要提供这样的功能。服务发现和注册的功能,是在 Spring Cloud 中进行提供。
2、自身的 acturator 所提供的【监控功能】,也需要与现有的监控对接。
3、没有配套的【安全管控】方案。
艿艿:关于这一点,艿艿也有点迷糊,Spring Security 是可以比较方便的集成到 Spring Boot 中,所以不晓得这里的【安全管控】的定义是什么。所以这一点,面试的时候回答,可以暂时先省略。
4、对于 REST 的落地,还需要自行结合实际进行 URI 的规范化工作
艿艿:这个严格来说,不算缺点。本身,是规范的范畴。
所以,上面的缺点,严格来说可能不太适合在面试中回答。艿艿认为,Spring Boot 的缺点主要是,因为自动配置 Spring Bean 的功能,我们可能无法知道,哪些 Bean 被进行创建了。这个时候,如果我们想要自定义一些 Bean ,可能存在冲突,或者不知道实际注入的情况。
Spring Boot、Spring MVC 和 Spring 有什么区别?
Spring 的完整名字,应该是 Spring Framework 。它提供了多个模块,Spring IoC、Spring AOP、Spring MVC 等等。所以,Spring MVC 是 Spring Framework 众多模块中的一个。
而 Spring Boot 是构造在 Spring Framework 之上的 Boot 启动器,旨在更容易的配置一个 Spring 项目。
总结说来,如下图所示:
Spring Boot 中的 Starter 是什么?
比较通俗的说法:
FROM 《Spring Boot 中 Starter 是什么》
比如我们要在 Spring Boot 中引入 Web MVC 的支持时,我们通常会引入这个模块 spring-boot-starter-web ,而这个模块如果解压包出来会发现里面什么都没有,只定义了一些 POM 依赖。如下图所示:
经过研究,Starter 主要用来简化依赖用的。比如我们之前做MVC时要引入日志组件,那么需要去找到log4j的版本,然后引入,现在有了Starter之后,直接用这个之后,log4j就自动引入了,也不用关心版本这些问题。
比较书名的说法:
FROM 《Spring Boot Starter 介绍》
依赖管理是任何复杂项目的关键部分。以手动的方式来实现依赖管理不太现实,你得花更多时间,同时你在项目的其他重要方面能付出的时间就会变得越少。
Spring Boot Starter 就是为了解决这个问题而诞生的。Starter POM 是一组方便的依赖描述符,您可以将其包含在应用程序中。您可以获得所需的所有 Spring 和相关技术的一站式服务,无需通过示例代码搜索和复制粘贴依赖。
Spring Boot 常用的 Starter 有哪些?
spring-boot-starter-web :提供 Spring MVC + 内嵌的 Tomcat 。
spring-boot-starter-data-jpa :提供 Spring JPA + Hibernate 。
spring-boot-starter-data-redis :提供 Redis 。
mybatis-spring-boot-starter :提供 MyBatis 。
创建一个 Spring Boot Project 的最简单的方法是什么?
Spring Initializr 是创建 Spring Boot Projects 的一个很好的工具。打开 “https://start.spring.io/” 网站,我们可以看到 Spring Initializr 工具,如下图所示:
另外,现在已经是 Spring Boot 的天下,所以更加是 Java Config 配置为主。
Spring Boot 的核心注解是哪个?
package cn.iocoder.skywalking.web01;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplicationpublic class Web01Application { public static void main(String[] args) { SpringApplication.run(Web01Application.class, args); }}
@SpringBootApplication 注解,就是 Spring Boot 的核心注解。
org.springframework.boot.autoconfigure.@SpringBootApplication 注解的代码如下:
// SpringBootApplication.java@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 { @AliasFor( annotation = EnableAutoConfiguration.class ) Class[] exclude() default {}; @AliasFor( annotation = EnableAutoConfiguration.class ) String[] excludeName() default {}; @AliasFor( annotation = ComponentScan.class, attribute = "basePackages" ) String[] scanBasePackages() default {}; @AliasFor( annotation = ComponentScan.class, attribute = "basePackageClasses" ) Class[] scanBasePackageClasses() default {};}
它组合了 3 个注解,详细说明,胖友看看 《Spring Boot 系列:@SpringBootApplication 注解》 。
@Configuration 注解,指定类是 Bean 定义的配置类。
@Configuration 注解,来自 spring-context 项目,用于 Java Config ,不是 Spring Boot 新带来的。
#ComponentScan 注解,扫描指定包下的 Bean 们。
@ComponentScan 注解,来自 spring-context 项目,用于 Java Config ,不是 Spring Boot 新带来的。
@EnableAutoConfiguration 注解,打开自动配置的功能。如果我们想要关闭某个类的自动配置,可以设置注解的 exclude 或 excludeName 属性。
@EnableAutoConfiguration 注解,来自 spring-boot-autoconfigure 项目,它才是 Spring Boot 新带来的。
什么是 Spring Boot 自动配置?
在 「Spring Boot 的核心注解是哪个?」 中,我们已经看到,使用 @@EnableAutoConfiguration 注解,打开 Spring Boot 自动配置的功能。具体如何实现的,可以看看如下两篇文章:
《@EnableAutoConfiguration 注解的工作原理》 。
《一个面试题引起的 Spring Boot 启动解析》
建议,能一边调试,一边看这篇文章。调试很简单,任一搭建一个 Spring Boot 项目即可。
如下是一个比较简单的总结:
Spring Boot 在启动时扫描项目所依赖的 jar 包,寻找包含spring.factories 文件的 jar 包。
根据 spring.factories 配置加载 AutoConfigure 类。
根据 @Conditional 等条件注解 的条件,进行自动配置并将 Bean 注入 Spring IoC 中。
Spring Boot 有哪几种读取配置的方式?
Spring Boot 目前支持 2 种读取配置:
@Value 注解,读取配置到属性。最最最常用。
另外,支持和 @PropertySource 注解一起使用,指定使用的配置文件。
@ConfigurationProperties 注解,读取配置到类上。
另外,支持和 @PropertySource 注解一起使用,指定使用的配置文件。
详细的使用方式,可以参考 《Spring Boot 读取配置的几种方式》 。
使用 Spring Boot 后,项目结构是怎么样的呢?
我们先来说说项目的分层。一般来说,主流的有两种方式:
方式一,controller、service、dao 三个包,每个包下面添加相应的 XXXController、YYYService、ZZZDAO 。
方式二,按照业务模块分包,每个包里面放 Controller、Service、DAO 类。例如,业务模块分成 user、order、item 等等包,在 user 包里放 UserController、UserService、UserDAO 类。
那么,使用 Spring Boot 的项目怎么分层呢?艿艿自己的想法
现在项目都会进行服务化分拆,每个项目不会特别复杂,所以建议使用【方式一】。
以前的项目,大多是单体的项目,动则项目几万到几十万的代码,当时多采用【方式二】。
下面是一个简单的 Spring Boot 项目的 Demo ,如下所示:
在使用 Spring MVC 时,我们一般会做如下几件事情:
实现自己项目需要的拦截器,并在 WebMvcConfigurer 实现类中配置。可参见 MVCConfiguration 类。
配置 @ControllerAdvice + @ExceptionHandler 注解,实现全局异常处理。可参见 GlobalExceptionHandler 类。
配置 @ControllerAdvice ,实现 ResponseBodyAdvice 接口,实现全局统一返回。可参见 GlobalResponseBodyAdvice 。
当然,有一点需要注意,WebMvcConfigurer、ResponseBodyAdvice、@ControllerAdvice、@ExceptionHandler 接口,都是 Spring MVC 框架自身已经有的东西。
spring-boot-starter-web 的依赖,帮我们解决的是 Spring MVC 的依赖以及相关的 Tomcat 等组件。
如何集成 Spring Boot 和 Spring Security ?
目前比较主流的安全框架有两个:
Spring Security
Apache Shiro
对于任何项目来说,安全认证总是少不了,同样适用于使用 Spring Boot 的项目。相对来说,Spring Security 现在会比 Apache Shiro 更流行。
Spring Boot 和 Spring Security 的配置方式比较简单:
引入 spring-boot-starter-security 的依赖。
继承 WebSecurityConfigurerAdapter ,添加自定义的安全配置。
当然,每个项目的安全配置是不同的,需要胖友自己选择。更多详细的使用,建议认真阅读如下文章:
《Spring Boot中 使用 Spring Security 进行安全控制》 ,快速上手。
《Spring Security 实现原理与源码解析系统 —— 精品合集》 ,深入源码。
另外,安全是一个很大的话题,感兴趣的胖友,可以看看 《Spring Boot 十种安全措施》 一文。
如何集成 Spring Boot 和 Spring Security OAuth2 ?
参见 《Spring Security OAuth2 入门》 文章,内容有点多。
如何集成 Spring Boot 和 JPA ?
引入 spring-boot-starter-data-jpa 的依赖。
在 application 配置文件中,加入 JPA 相关的少量配置。当然,数据库的配置也要添加进去。
具体编码。
详细的使用,胖友可以参考:
《一起来学 SpringBoot 2.x | 第六篇:整合 Spring Data JPA》
有两点需要注意:
Spring Boot 2 默认使用的数据库连接池是 HikariCP ,目前最好的性能的数据库连接池的实现。
spring-boot-starter-data-jpa 的依赖,使用的默认 JPA 实现是 Hibernate 5.X 。
如何集成 Spring Boot 和 MyBatis ?
引入 mybatis-spring-boot-starter 的依赖。
在 application 配置文件中,加入 MyBatis 相关的少量配置。当然,数据库的配置也要添加进去。
具体编码。
详细的使用,胖友可以参考:
《一起来学 SpringBoot 2.x | 第七篇:整合 Mybatis》
如何集成 Spring Boot 和 RabbitMQ ?
引入 spring-boot-starter-amqp 的依赖
在 application 配置文件中,加入 RabbitMQ 相关的少量配置。
具体编码。
详细的使用,胖友可以参考:
《一起来学 SpringBoot 2.x | 第十二篇:初探 RabbitMQ 消息队列》
《一起来学 SpringBoot 2.x | 第十三篇:RabbitMQ 延迟队列》
如何集成 Spring Boot 和 Kafka ?
引入 spring-kafka 的依赖。
在 application 配置文件中,加入 Kafka 相关的少量配置。
具体编码。
详细的使用,胖友可以参考:
《Spring Boot系列文章(一):SpringBoot Kafka 整合使用》
如何集成 Spring Boot 和 RocketMQ ?
引入 rocketmq-spring-boot 的依赖。
在 application 配置文件中,加入 RocketMQ 相关的少量配置。
具体编码。
详细的使用,胖友可以参考:
《我用这种方法在 Spring 中实现消息的发送和消费》
Spring Boot 支持哪些日志框架?
Spring Boot 支持的日志框架有:
Logback
Log4j2
Log4j
Java Util Logging
默认使用的是 Logback 日志框架,也是目前较为推荐的,具体配置,可以参见 《一起来学 SpringBoot 2.x | 第三篇:SpringBoot 日志配置》 。
因为 Log4j2 的性能更加优秀,也有人在生产上使用,可以参考 《Spring Boot Log4j2 日志性能之巅》 配置。