50 個 經(jīng)典 Spring 面試題
點擊上方 java項目開發(fā) ,選擇 星標(biāo) 公眾號
重磅資訊,干貨,第一時間送達
---
1、基礎(chǔ)概念
1.1. 不同版本的 Spring Framework 有哪些主要功能?

1.2. 什么是 Spring Framework?
Spring 是一個開源應(yīng)用框架,旨在降低應(yīng)用程序開發(fā)的復(fù)雜度。
它是輕量級、松散耦合的。
它具有分層體系結(jié)構(gòu),允許用戶選擇組件,同時還為 J2EE 應(yīng)用程序開發(fā)提供了一個有凝聚力的框架。
它可以集成其他框架,如 Structs、Hibernate、EJB 等,所以又稱為框架的框架。
本篇是 Spring 框架面試題,關(guān)于 Spring 實戰(zhàn)可以關(guān)注公眾號「Java后端」回復(fù) 666 下載~
1.3. 列舉 Spring Framework 的優(yōu)點。
由于 Spring Frameworks 的分層架構(gòu),用戶可以自由選擇自己需要的組件。
Spring Framework 支持 POJO(Plain Old Java Object) 編程,從而具備持續(xù)集成和可測試性。
由于依賴注入和控制反轉(zhuǎn),JDBC 得以簡化。
它是開源免費的。
1.4. Spring Framework 有哪些不同的功能?
輕量級 - Spring 在代碼量和透明度方面都很輕便。
IOC - 控制反轉(zhuǎn)
AOP - 面向切面編程可以將應(yīng)用業(yè)務(wù)邏輯和系統(tǒng)服務(wù)分離,以實現(xiàn)高內(nèi)聚。
容器 - Spring 負(fù)責(zé)創(chuàng)建和管理對象(Bean)的生命周期和配置。
MVC - 對 web 應(yīng)用提供了高度可配置性,其他框架的集成也十分方便。
事務(wù)管理 - 提供了用于事務(wù)管理的通用抽象層。Spring 的事務(wù)支持也可用于容器較少的環(huán)境。
JDBC 異常 - Spring 的 JDBC 抽象層提供了一個異常層次結(jié)構(gòu),簡化了錯誤處理策略。
1.5. Spring Framework 中有多少個模塊,它們分別是什么?

Spring 核心容器 – 該層基本上是 Spring Framework 的核心。它包含以下模塊:
Spring Core
Spring Bean
SpEL (Spring Expression Language)
Spring Context
數(shù)據(jù)訪問/集成 – 該層提供與數(shù)據(jù)庫交互的支持。它包含以下模塊:
JDBC (Java DataBase Connectivity)
ORM (Object Relational Mapping)
OXM (Object XML Mappers)
JMS (Java Messaging Service)
Transaction
Web – 該層提供了創(chuàng)建 Web 應(yīng)用程序的支持。它包含以下模塊:
Web
Web – Servlet
Web – Socket
Web – Portlet
AOP – 該層支持面向切面編程
Instrumentation – 該層為類檢測和類加載器實現(xiàn)提供支持。
Test – 該層為使用 JUnit 和 TestNG 進行測試提供支持。
幾個雜項模塊:
Messaging – 該模塊為 STOMP 提供支持。它還支持注解編程模型,該模型用于從 WebSocket 客戶端路由和處理 STOMP 消息
Aspects – 該模塊為與 AspectJ 的集成提供支持。
Spring 配置文件是 XML 文件。該文件主要包含類信息。它描述了這些類是如何配置以及相互引入的。但是,XML 配置文件冗長且更加干凈。如果沒有正確規(guī)劃和編寫,那么在大項目中管理變得非常困難。
1.7. Spring 應(yīng)用程序有哪些不同組件?
Spring 應(yīng)用一般有以下組件:
接口 - 定義功能。
Bean 類 - 它包含屬性,setter 和 getter 方法,函數(shù)等。
Spring 面向切面編程(AOP) - 提供面向切面編程的功能。
Bean 配置文件 - 包含類的信息以及如何配置它們。
用戶程序 - 它使用接口。
1.8. 使用 Spring 有哪些方式?
使用 Spring 有以下方式:
作為一個成熟的 Spring Web 應(yīng)用程序。
作為第三方 Web 框架,使用 Spring Frameworks 中間層。
用于遠程使用。
作為企業(yè)級 Java Bean,它可以包裝現(xiàn)有的 POJO(Plain Old Java Objects)。
2、依賴注入(Ioc)
2.1. 什么是 Spring IOC 容器?
Spring 框架的核心是 Spring 容器。容器創(chuàng)建對象,將它們裝配在一起,配置它們并管理它們的完整生命周期。Spring 容器使用依賴注入來管理組成應(yīng)用程序的組件。
容器通過讀取提供的配置元數(shù)據(jù)來接收對象進行實例化,配置和組裝的指令。該元數(shù)據(jù)可以通過 XML,Java 注解或 Java 代碼提供。

img
2.2. 什么是依賴注入?
在依賴注入中,您不必創(chuàng)建對象,但必須描述如何創(chuàng)建它們。您不是直接在代碼中將組件和服務(wù)連接在一起,而是描述配置文件中哪些組件需要哪些服務(wù)。由 IoC 容器將它們裝配在一起。
2.3. 可以通過多少種方式完成依賴注入?
通常,依賴注入可以通過三種方式完成,即:
構(gòu)造函數(shù)注入
setter 注入
接口注入
在 Spring Framework 中,僅使用構(gòu)造函數(shù)和 setter 注入。
2.4. 區(qū)分構(gòu)造函數(shù)注入和 setter 注入。

2.5. spring 中有多少種 IOC 容器?
BeanFactory - BeanFactory 就像一個包含 bean 集合的工廠類。它會在客戶端要求時實例化 bean。
ApplicationContext - ApplicationContext 接口擴展了 BeanFactory 接口。它在 BeanFactory 基礎(chǔ)上提供了一些額外的功能。
2.6. 區(qū)分 BeanFactory 和 ApplicationContext。

2.7. 列舉 IoC 的一些好處。
IoC 的一些好處是:
它將最小化應(yīng)用程序中的代碼量。
它將使您的應(yīng)用程序易于測試,因為它不需要單元測試用例中的任何單例或 JNDI 查找機制。
它以最小的影響和最少的侵入機制促進松耦合。
它支持即時的實例化和延遲加載服務(wù)。
2.8. Spring IoC 的實現(xiàn)機制。
Spring 中的 IoC 的實現(xiàn)原理就是工廠模式加反射機制。
示例:
interface Fruit {
public abstract void eat();
}
class Apple implements Fruit {
public void eat(){
System.out.println("Apple");
}
}
class Orange implements Fruit {
public void eat(){
System.out.println("Orange");
}
}
class Factory {
public static Fruit getInstance(String ClassName) {
Fruit f=null;
try {
f=(Fruit)Class.forName(ClassName).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return f;
}
}
class Client {
public static void main(String[] a) {
Fruit f=Factory.getInstance("io.github.dunwu.spring.Apple");
if(f!=null){
f.eat();
}
}
}3.1. 什么是 spring bean?
它們是構(gòu)成用戶應(yīng)用程序主干的對象。
Bean 由 Spring IoC 容器管理。
它們由 Spring IoC 容器實例化,配置,裝配和管理。
Bean 是基于用戶提供給容器的配置元數(shù)據(jù)創(chuàng)建。
3.2. spring 提供了哪些配置方式?
基于 xml 配置
bean 所需的依賴項和服務(wù)在 XML 格式的配置文件中指定。這些配置文件通常包含許多 bean 定義和特定于應(yīng)用程序的配置選項。它們通常以 bean 標(biāo)簽開頭。例如:
<bean id="studentbean" class="org.edureka.firstSpring.StudentBean">
<property name="name" value="Edureka"></property>
</bean>基于注解配置
您可以通過在相關(guān)的類,方法或字段聲明上使用注解,將 bean 配置為組件類本身,而不是使用 XML 來描述 bean 裝配。默認(rèn)情況下,Spring 容器中未打開注解裝配。因此,您需要在使用它之前在 Spring 配置文件中啟用它。例如:
<beans>
<context:annotation-config/>
<!-- bean definitions go here -->
</beans>基于 Java API 配置
Spring 的 Java 配置是通過使用 @Bean 和 @Configuration 來實現(xiàn)。
@Bean 注解扮演與 <bean /> 元素相同的角色。
@Configuration 類允許通過簡單地調(diào)用同一個類中的其他 @Bean 方法來定義 bean 間依賴關(guān)系。
例如:
@Configuration
public class StudentConfig {
@Bean
public StudentBean myStudent() {
return new StudentBean();
}
}3.3. spring 支持集中 bean scope?
Spring bean 支持 5 種 scope:
Singleton - 每個 Spring IoC 容器僅有一個單實例。
Prototype - 每次請求都會產(chǎn)生一個新的實例。
Request - 每一次 HTTP 請求都會產(chǎn)生一個新的實例,并且該 bean 僅在當(dāng)前 HTTP 請求內(nèi)有效。
Session - 每一次 HTTP 請求都會產(chǎn)生一個新的 bean,同時該 bean 僅在當(dāng)前 HTTP session 內(nèi)有效。
Global-session - 類似于標(biāo)準(zhǔn)的 HTTP Session 作用域,不過它僅僅在基于 portlet 的 web 應(yīng)用中才有意義。Portlet 規(guī)范定義了全局 Session 的概念,它被所有構(gòu)成某個 portlet web 應(yīng)用的各種不同的 portlet 所共享。在 global session 作用域中定義的 bean 被限定于全局 portlet Session 的生命周期范圍內(nèi)。如果你在 web 中使用 global session 作用域來標(biāo)識 bean,那么 web 會自動當(dāng)成 session 類型來使用。
僅當(dāng)用戶使用支持 Web 的 ApplicationContext 時,最后三個才可用。更多spring內(nèi)容
3.4. spring bean 容器的生命周期是什么樣的?
spring bean 容器的生命周期流程如下:
Spring 容器根據(jù)配置中的 bean 定義中實例化 bean
Spring 使用依賴注入填充所有屬性,如 bean 中所定義的配置。
如果 bean 實現(xiàn) BeanNameAware 接口,則工廠通過傳遞 bean 的 ID 來調(diào)用 setBeanName()。
如果 bean 實現(xiàn) BeanFactoryAware 接口,工廠通過傳遞自身的實例來調(diào)用 setBeanFactory()。
如果存在與 bean 關(guān)聯(lián)的任何 BeanPostProcessors,則調(diào)用 preProcessBeforeInitialization() 方法。
如果為 bean 指定了 init 方法( <bean>的 init-method 屬性),那么將調(diào)用它。
最后,如果存在與 bean 關(guān)聯(lián)的任何 BeanPostProcessors,則將調(diào)用 postProcessAfterInitialization() 方法。
如果 bean 實現(xiàn) DisposableBean 接口,當(dāng) spring 容器關(guān)閉時,會調(diào)用 destory()。
如果為 bean 指定了 destroy 方法( <bean>的 destroy-method 屬性),那么將調(diào)用它。

3.5. 什么是 spring 的內(nèi)部 bean?
public class Student {
private Person person;
//Setters and Getters
}
public class Person {
private String name;
private String address;
//Setters and Getters
}<bean id=“StudentBean" class="com.edureka.Student">
<property name="person">
<!--This is inner bean -->
<bean class="com.edureka.Person">
<property name="name" value=“Scott"></property>
<property name="address" value=“Bangalore"></property>
</bean>
</property>
</bean>no - 這是默認(rèn)設(shè)置,表示沒有自動裝配。應(yīng)使用顯式 bean 引用進行裝配。 byName - 它根據(jù) bean 的名稱注入對象依賴項。它匹配并裝配其屬性與 XML 文件中由相同名稱定義的 bean。 byType - 它根據(jù)類型注入對象依賴項。如果屬性的類型與 XML 文件中的一個 bean 名稱匹配,則匹配并裝配屬性。 構(gòu)造函數(shù) - 它通過調(diào)用類的構(gòu)造函數(shù)來注入依賴項。它有大量的參數(shù)。 autodetect - 首先容器嘗試通過構(gòu)造函數(shù)使用 autowire 裝配,如果不能,則嘗試通過 byType 自動裝配。
覆蓋的可能性 - 您始終可以使用<constructor-arg> 和 <property>設(shè)置指定依賴項,這將覆蓋自動裝配。 基本元數(shù)據(jù)類型 - 簡單屬性(如原數(shù)據(jù)類型,字符串和類)無法自動裝配。 令人困惑的性質(zhì) - 總是喜歡使用明確的裝配,因為自動裝配不太精確。
@Controller - 用于 Spring MVC 項目中的控制器類。 @Service - 用于服務(wù)類。 @RequestMapping - 用于在控制器處理程序方法中配置 URI 映射。 @ResponseBody - 用于發(fā)送 Object 作為響應(yīng),通常用于發(fā)送 XML 或 JSON 數(shù)據(jù)作為響應(yīng)。 @PathVariable - 用于將動態(tài)值從 URI 映射到處理程序方法參數(shù)。 @Autowired - 用于在 spring bean 中自動裝配依賴項。 @Qualifier - 使用 @Autowired 注解,以避免在存在多個 bean 類型實例時出現(xiàn)混淆。 @Scope - 用于配置 spring bean 的范圍。 @Configuration,@ComponentScan 和 @Bean - 用于基于 java 的配置。 @Aspect,@Before,@After,@Around,@Pointcut - 用于切面編程(AOP)。
@Component:這將 java 類標(biāo)記為 bean。它是任何 Spring 管理組件的通用構(gòu)造型。spring 的組件掃描機制現(xiàn)在可以將其拾取并將其拉入應(yīng)用程序環(huán)境中。 @Controller:這將一個類標(biāo)記為 Spring Web MVC 控制器。標(biāo)有它的 Bean 會自動導(dǎo)入到 IoC 容器中。 @Service:此注解是組件注解的特化。它不會對 @Component 注解提供任何其他行為。您可以在服務(wù)層類中使用 @Service 而不是 @Component,因為它以更好的方式指定了意圖。 @Repository:這個注解是具有類似用途和功能的 @Component 注解的特化。它為 DAO 提供了額外的好處。它將 DAO 導(dǎo)入 IoC 容器,并使未經(jīng)檢查的異常有資格轉(zhuǎn)換為 Spring DataAccessException。
public class Employee {
private String name;
@Required
public void setName(String name){
this.name=name;
}
public string getName(){
return name;
}
}public class Employee {
private String name;
@Autowired
public void setName(String name) {
this.name=name;
}
public string getName(){
return name;
}
}4.6. @Qualifier 注解有什么用?
public class Employee {
private String name;
@Autowired
public void setName(String name) {
this.name=name;
}
public string getName() {
return name;
}
}public class EmpAccount {
private Employee emp;
@Autowired
@Qualifier(emp1)
public void showName() {
System.out.println(“Employee name : ”+emp.getName);
}
}類級別:映射請求的 URL 方法級別:映射 URL 以及 HTTP 請求方法

JdbcTemplate SimpleJdbcTemplate NamedParameterJdbcTemplate SimpleJdbcInsert SimpleJdbcCall
使用 Hibernate 模板和回調(diào)進行控制反轉(zhuǎn) 擴展 HibernateDAOSupport 并應(yīng)用 AOP 攔截器節(jié)點
程序化事務(wù)管理:在此過程中,在編程的幫助下管理事務(wù)。它為您提供極大的靈活性,但維護起來非常困難。 聲明式事務(wù)管理:在此,事務(wù)管理與業(yè)務(wù)代碼分離。僅使用注解或基于 XML 的配置來管理事務(wù)。
Hibernate iBatis JPA JDO OJB

Aspect - Aspect 是一個實現(xiàn)交叉問題的類,例如事務(wù)管理。方面可以是配置的普通類,然后在 Spring Bean 配置文件中配置,或者我們可以使用 Spring AspectJ 支持使用 @Aspect 注解將類聲明為 Aspect。 Advice - Advice 是針對特定 JoinPoint 采取的操作。在編程方面,它們是在應(yīng)用程序中達到具有匹配切入點的特定 JoinPoint 時執(zhí)行的方法。您可以將 Advice 視為 Spring 攔截器(Interceptor)或 Servlet 過濾器(filter)。 Advice Arguments - 我們可以在 advice 方法中傳遞參數(shù)。我們可以在切入點中使用 args() 表達式來應(yīng)用于與參數(shù)模式匹配的任何方法。如果我們使用它,那么我們需要在確定參數(shù)類型的 advice 方法中使用相同的名稱。 Pointcut - Pointcut 是與 JoinPoint 匹配的正則表達式,用于確定是否需要執(zhí)行 Advice。Pointcut 使用與 JoinPoint 匹配的不同類型的表達式。Spring 框架使用 AspectJ Pointcut 表達式語言來確定將應(yīng)用通知方法的 JoinPoint。 JoinPoint - JoinPoint 是應(yīng)用程序中的特定點,例如方法執(zhí)行,異常處理,更改對象變量值等。在 Spring AOP 中,JoinPoint 始終是方法的執(zhí)行器。
Before - 這些類型的 Advice 在 joinpoint 方法之前執(zhí)行,并使用 @Before 注解標(biāo)記進行配置。 After Returning - 這些類型的 Advice 在連接點方法正常執(zhí)行后執(zhí)行,并使用@AfterReturning 注解標(biāo)記進行配置。 After Throwing - 這些類型的 Advice 僅在 joinpoint 方法通過拋出異常退出并使用 @AfterThrowing 注解標(biāo)記配置時執(zhí)行。 After (finally) - 這些類型的 Advice 在連接點方法之后執(zhí)行,無論方法退出是正常還是異常返回,并使用 @After 注解標(biāo)記進行配置。 Around - 這些類型的 Advice 在連接點之前和之后執(zhí)行,并使用 @Around 注解標(biāo)記進行配置。
靜態(tài)代理 - 指使用 AOP 框架提供的命令進行編譯,從而在編譯階段就可生成 AOP 代理類,因此也稱為編譯時增強; 編譯時編織(特殊編譯器實現(xiàn)) 類加載時編織(特殊的類加載器實現(xiàn))。 動態(tài)代理 - 在運行時在內(nèi)存中“臨時”生成 AOP 動態(tài)代理類,因此也被稱為運行時增強。 JDK 動態(tài)代理 CGLIB
Advice + Target Object = Proxy
7、MVC

向服務(wù)器發(fā)送 HTTP 請求,請求被前端控制器 DispatcherServlet 捕獲。 DispatcherServlet 根據(jù) -servlet.xml 中的配置對請求的 URL 進行解析,得到請求資源標(biāo)識符(URI)。然后根據(jù)該 URI,調(diào)用 HandlerMapping 獲得該 Handler 配置的所有相關(guān)的對象(包括 Handler 對象以及 Handler 對象對應(yīng)的攔截器),最后以HandlerExecutionChain 對象的形式返回。 DispatcherServlet 根據(jù)獲得的Handler,選擇一個合適的 HandlerAdapter。(附注:如果成功獲得HandlerAdapter后,此時將開始執(zhí)行攔截器的 preHandler(…)方法)。 提取Request中的模型數(shù)據(jù),填充Handler入?yún)ⅲ_始執(zhí)行Handler(Controller)。在填充Handler的入?yún)⑦^程中,根據(jù)你的配置,Spring 將幫你做一些額外的工作:
HttpMessageConveter:將請求消息(如 Json、xml 等數(shù)據(jù))轉(zhuǎn)換成一個對象,將對象轉(zhuǎn)換為指定的響應(yīng)信息。 數(shù)據(jù)轉(zhuǎn)換:對請求消息進行數(shù)據(jù)轉(zhuǎn)換。如 String轉(zhuǎn)換成Integer、Double等。數(shù)據(jù)根式化:對請求消息進行數(shù)據(jù)格式化。如將字符串轉(zhuǎn)換成格式化數(shù)字或格式化日期等。 數(shù)據(jù)驗證:驗證數(shù)據(jù)的有效性(長度、格式等),驗證結(jié)果存儲到 BindingResult或Error中。
來源 | 靜默虛空
推薦閱讀:
怎么接私貨?這個渠道你100%有用!請收藏!喜歡文章,點個在看


