前言:
今天看到了几道SpringBoot的面试题,觉得挺不错的,就在这里记录一下,方便以后自己查阅。

什么是SpringBoot?

答: SpringBoot的诞生和Spring是息息相关的,Spring Boot是Spring发展到一定程度的一个产物,但他并不是Spring的替代品,SpringBoot是为了让程序更好的使用Spring。Spring大量繁琐的XML配置和第三方整合配置,让Spring使用者痛苦不已,这是SpringBoot诞生,简化了Spring应用初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。Spring Boot其实就是一个整合很多可插拔的组件(框架),内嵌了使用工具(Tomcat、Jetty),方便开发人员快速搭建和开发的一个框架。SpringBoot最好的特性之一就是它利用现有的Spring项目和第三方项目来开发适合生产的应用程序。

Spring Boot的主要优点?

  • 开发基于Spring的应用程序很容易
  • SpringBoot项目所需的开发或工程时间明显减少,通常会提高整体生产力。
  • SpringBoot不需要编写大量样板代码,XML配置和注释。
  • Spring引导应用程序可以很容易地与Spring生态系统集成,比如Spring JDBC、Spring ORM、Spring Data、Spring Security等。
  • Spring Boot遵循"固执己见的默认配置",以减少开发工作(默认配置可以修改)
  • Spring Boot 应用程序提供嵌入式HTTP服务器,如Tomcat和Jetty,可以轻松地开发和测试web应用程序。
  • Spring Boot提供命令行接口(CLI)工具,用于开发和测试Spring Boot应用程序,如Java或Groovy。
  • Spring Boot提供了多种插件,可以使用内置工具(如Maven和Gradle)开发和测试Spring Boot应用程序。

为什么需要Spring Boot?

Spring FrameWork旨在简化J2EE企业应用程序开发,Spring Boot FramWork旨在简化Spring开发。

什么是Spring Boot Starters?

Spring Boot Starters 是一系列依赖关系的集合,因为他的存在,项目的依赖之间的关系对我们来说变得更加简单了。例如:在没有Spring Boot Starters之前,我们开发REST服务或WEB应用程序时,我们需要使用像Spring MVC,Tomcat和jackson这样的库,这些依赖我们需要手动一个一个添加。但是有了Spring Boot Starters我们只需要一个只需添加一个Sping-boot-starter-web一个依赖就可以了,这个依赖包含的字依赖中包含了我们开发REST服务需要的所有依赖。

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

如何在Spring Boot 应用程序中使用Jetty而不是Tomcat

Spring Boot Web starter使用Tomcat作为默认的嵌入式Servlet容器,如果你想使用Jetty的话只需要修改pom.xml(MAVEN)或者build.gradle(Gradle)就可以了。

<!--从Web启动器依赖中排除Tomcat-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--添加Jetty依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>

介绍一下@SpringBootApplication注解

package org.springframework.boot.autoconfigure;
@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 {
......
}

package org.springframework.boot;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {

}

从中可以看出来大概可以把@SpringBootApplication看作是@Configuration、@EnableAutoConfiguration、@ComponentScan注解的集合。

  • @EnableAutoConfiguration 启动SpringBoot的自动配置机制
  • @ComponentScan: 扫描被@Component(@Service,@Controller)注解的bean,注解默认会扫描该类所在包下所有的类。
  • @Configuration: 允许在上下文中注册额外的bean或导入其他配置类。

(重点掌握)Spring Boot的自动配置是如何实现的

这个是因为@SpringBootApplication 注解的原因,在上一个问题中已经提到了这个注解。我们知道 @SpringBootApplication 看作是 @Configuration、@EnableAutoConfiguration、@ComponentScan 注解的集合。

  • @EnableAutoConfiguration:启用 SpringBoot 的自动配置机制
  • @ComponentScan: 扫描被@Component (@Service,@Controller)注解的bean,注解默认会扫描该类所在的包下所有的类。
  • @Configuration:允许在上下文中注册额外的bean或导入其他配置类

@EnableAutoConfiguration是启动自动配置的关键,源码如下(可以采用debug进行断点调试):

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(EnableAutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {

/**
* Exclude specific auto-configuration classes such that they will never be applied.
* @return the classes to exclude
*/
Class<?>[] exclude() default {};

/**
* Exclude specific auto-configuration class names such that they will never be
* applied.
* @return the class names to exclude
* @since 1.3.0
*/
String[] excludeName() default {};

}

@EnbaleAutoConfiguration注解通过Spring提供@Import注解导入EnableAutoConfigurationImportSelector类(@Import 注解可以导入配置类或者Bean到当前类中)

/**
* Return the auto-configuration class names that should be considered. By default
* this method will load candidates using {@link SpringFactoriesLoader} with
* {@link #getSpringFactoriesLoaderFactoryClass()}.
* @param metadata the source metadata
* @param attributes the {@link #getAttributes(AnnotationMetadata) annotation
* attributes}
* @return a list of candidate configurations
*/
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,
AnnotationAttributes attributes) {
return SpringFactoriesLoader.loadFactoryNames(
getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());
}

​EnableAutoConfigurationImportSelector​​​类中getCandidateConfigurations方法会将所有自动配置类的信息以List的形式返回。这些配置信息会被Spring容器做bean来管理。
自动配置信息就有了,自动配置呢?
@Conditional注解。@ConditionalOnClass(指定的类必须存在于类路径下),@ConditionalOnBean(容器中是否有指定的Bean)等等都是对@Conditional注解的扩展。拿 Spring Security 的自动配置举个例子:
SecurityAutoConfiguration中导入了WebSecurityEnablerConfiguration类,WebSecurityEnablerConfiguration源代码如下:

@Configuration
@ConditionalOnBean(WebSecurityConfigurerAdapter.class)
@ConditionalOnMissingBean(name = BeanIds.SPRING_SECURITY_FILTER_CHAIN)
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
@EnableWebSecurity
public class WebSecurityEnablerConfiguration {

}

WebSecurityEnablerConfiguration类中使用@ConditionalOnBean指定了容器中必须还有WebSecurityConfigurerAdapter 类或其实现类。所以,一般情况下 Spring Security 配置类都会去实现 WebSecurityConfigurerAdapter,这样自动将配置就完成了。

Spring Boot支持哪些嵌入式web容器?

Spring Boot支持以下嵌入式servlet容器:

Name

Servlet Version

Tomcat 9.0

4.0

Jetty 9.4

3.1

Undertow 2.0

4.0

可以将Spring引导应用程序部署到任何Servlet3.1+ 兼容的Web容器中。

什么是Spring Security

Spring Security应该属于Spring全家桶中学习曲线比较陡峭的几个模块之一,下面我将从起源和定义这两个方面来简单介绍一下它。

  • 起源:Spring Security实际上起源于Acegi Security,这个框架能为基于Spring的企业应用提供强大而灵活安全访问控制解决方案,并且框架这个充分利用Spring的IOC和Aop功能,提供声明式安全访问控制的功能。后面,随着这个项目的发展,Acegi Security成为了Spring的官方子项目,后来被命名为"Spring Security"
  • Spring Security 是一个功能强大且高度可以定制的框架,侧重于为Java 应用程序提供身份验证和授权.它是用于保护基于Spring的应用程序的实际标准。