黑木崖--SpringBoot系列之常見面試題

簡單的小宋發表於2020-11-27

因為之前出了秒殺面試的博文,所以這裡小宋專門寫一篇部落格,講一講常見的SpringBoot面試題。直接進入主題。

SpringBoot面試題

什麼是 Spring Boot?

首先,重要的是要理解 Spring Boot 並不是一個框架,它是一種建立獨立應用程式的更簡單方法,只需要很少或沒有配置(相比於 Spring 來說)。Spring Boot最好的特性之一是它利用現有的 Spring 專案和第三方專案來開發適合生產的應用程式。

說出使用Spring Boot的主要優點?

  1. 開發基於 Spring 的應用程式很容易。
  2. Spring Boot 專案所需的開發或工程時間明顯減少,通常會提高整體生產力。
  3. Spring Boot不需要編寫大量樣板程式碼、XML配置和註釋。
  4. Spring Boot引導應用程式可以很容易地與Spring生態系統整合,如Spring JDBC、Spring ORM、Spring Data、Spring Security等。
  5. Spring Boot遵循“固執己見的預設配置”,以減少開發工作(預設配置可以修改)。
  6. Spring Boot 應用程式提供嵌入式HTTP伺服器,如Tomcat和Jetty,可以輕鬆地開發和測試web應用程式。(這點很贊!普通執行Java程式的方式就能執行基於Spring Boot web 專案,省事很多)
  7. Spring Boot提供命令列介面(CLI)工具,用於開發和測試Spring Boot應用程式,如Java或Groovy。
  8. Spring Boot提供了多種外掛,可以使用內建工具(如Maven和Gradle)開發和測試Spring Boot應用程式。

為什麼需要Spring Boot?

Spring Framework旨在簡化J2EE企業應用程式開發。Spring Boot Framework旨在簡化Spring開發。
在這裡插入圖片描述

什麼是 Spring Boot Starters?

Spring Boot Starters 是一系列依賴關係的集合,因為它的存在,專案的依賴之間的關係對我們來說變的更加簡單了。舉個例子:在沒有Spring Boot Starters之前,我們開發REST服務或Web應用程式時; 我們需要使用像Spring MVC,Tomcat和Jackson這樣的庫,這些依賴我們需要手動一個一個新增。但是,有了 Spring Boot Starters 我們只需要一個只需新增一個spring-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)就可以了。
Maven:

<!--從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>

Gradle:

compile("org.springframework.boot:spring-boot-starter-web") {
     exclude group: 'org.springframework.boot', module: 'spring-boot-starter-tomcat'
}
compile("org.springframework.boot:spring-boot-starter-jetty")

說個題外話,從上面可以看出使用 Gradle 更加簡潔明瞭,但是國內目前還是 Maven 使用的多一點。

介紹一下@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 註解的集合。根據 SpringBoot官網,這三個註解的作用分別是:

  1. @EnableAutoConfiguration:啟用 SpringBoot 的自動配置機制
  2. @ComponentScan: 掃描被@Component (@Service,@Controller)註解的bean,註解預設會掃描該類所在的包下所有的類。
  3. @Configuration:允許在上下文中註冊額外的bean或匯入其他配置類

Spring Boot 的自動配置是如何實現的?(重要)

這個是因為@SpringBootApplication 註解的原因,在上一個問題中已經提到了這個註解。我們知道 @SpringBootApplication 看作是 @Configuration、@EnableAutoConfiguration、@ComponentScan 註解的集合。

  1. @EnableAutoConfiguration:啟用 SpringBoot 的自動配置機制
  2. @ComponentScan: 掃描被@Component (@Service,@Controller)註解的bean,註解預設會掃描該類所在的包下所有的類。
  3. @Configuration:允許在上下文中註冊額外的bean或匯入其他配置類

@EnableAutoConfiguration是啟動自動配置的關鍵,原始碼如下(建議自己打斷點除錯,走一遍基本的流程):

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.context.annotation.Import;

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
    String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

    Class<?>[] exclude() default {};

    String[] excludeName() default {};
}

@EnableAutoConfiguration 註解通過Spring 提供的 @Import 註解匯入了AutoConfigurationImportSelector類(@Import 註解可以匯入配置類或者Bean到當前類中)。

AutoConfigurationImportSelector類中getCandidateConfigurations方法會將所有自動配置類的資訊以 List 的形式返回。這些配置資訊會被 Spring 容器作 bean 來管理。

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
		List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
				getBeanClassLoader());
		Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you "
				+ "are using a custom packaging, make sure that file is correct.");
		return configurations;
	}

自動配置資訊有了,那麼自動配置還差什麼呢?

@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容器:

NameServlet Version
Tomcat 9.04.0
Jetty 9.43.1
Undertow 2.04.0

您還可以將Spring boot引導應用程式部署到任何Servlet 3.1+相容的 Web 容器中。

這就是你為什麼可以通過直接像執行 普通 Java 專案一樣執行 SpringBoot 專案。這樣的確省事了很多,方便了我們進行開發,降低了學習難度。

什麼是Spring Security ?

Spring Security 應該屬於 Spring 全家桶中學習曲線比較陡峭的幾個模組之一,下面我將從起源和定義這兩個方面來簡單介紹一下它。

  • 起源: Spring Security 實際上起源於 Acegi Security,這個框架能為基於 Spring 的企業應用提供強大而靈活安全訪問控制解決方案,並且框架這個充分利用 Spring 的 IoC 和 AOP 功能,提供宣告式安全訪問控制的功能。後面,隨著這個專案發展, Acegi Security 成為了Spring官方子專案,後來被命名為 “Spring Security”。
  • 定義:Spring Security 是一個功能強大且可以高度定製的框架,側重於為Java 應用程式提供身份驗證和授權。——官方介紹。

相關文章