Spring = SpringMVC以及面試題

https://javadoop.com/

(1)什麼是SpringMVC

Spring MVC是一種基於Java的實現了Web MVC設計模式的請求驅動類型的輕量級Web框架,即使用了MVC架構模式的思想,將Web層進行職責解耦,基於請求驅動指的就是使用請求-響應模型,SpringMVC框架的目的就是幫助我們簡化開發。

Spring MVC 實現了即用的 MVC 的核心概念。它爲控制器和處理程序提供了大量與此模式相關的功能。並且當向 MVC 添加反轉控制(Inversion of Control,IoC)時,它使應用程序高度解耦,提供了通過簡單的配置更改即可動態更改組件的靈活性。Spring MVC 提供了完全控制應用程序的各個方面的力量。Spring 的 Web MVC 模塊是圍繞 DispatcherServlet 而設計的。DispatcherServlet 給處理程序分派請求,執行視圖解析,並且處理語言環境和主題解析,並且還爲上傳文件提供支持。

Spring MVC屬於Spring Frame Work的後續產品,已經融合在Spring Web Flow裏面。Spring框架最初由Rod Johnson撰寫,並於2003年6月根據Apache 2.0許可證首次發佈。

Spring MVC框架提供了MVC(模型 - 視圖 - 控制器)架構和用於開發靈活和鬆散耦合的Web應用程序的組件。 MVC模式導致應用程序的不同方面(輸入邏輯,業務邏輯和UI邏輯)分離,同時提供這些元素之間的鬆散耦合。

模型(Model)封裝了應用程序數據,通常它們將由POJO類組成。視圖(View)負責渲染模型數據,一般來說它生成客戶端瀏覽器可以解釋HTML輸出。控制器(Controller)負責處理用戶請求並構建適當的模型,並將其傳遞給視圖進行渲染。

(2)如何學習SpringMVC

SpringMVC的優點其實只有一個:就是讓使用者只關心核心業務的開發,框架幫你屏蔽原有技術跟業務開發無關的各類技術問題。因爲SpringMVC這類框架之所以優秀,就是它們在這點上做的太好了,以至於很多使用它的程序員都已經不清楚原有技術的真實面目,因此我們要將SpringMVC理解的更好,使用的更加熟練和深入,這裏我們就要跳出SpringMVC的技術,到SpringMVC技術的源頭servlet,仔細研究下servlet的特點,只有這樣我們才能把SpringMVC框架學的更好。

(3)什麼是Spring框架:

Spring 是一種輕量級開發框架,旨在提高開發人員的開發效率以及系統的可維護性。Spring 官網:https://spring.io/

我們一般說 Spring 框架指的都是 Spring Framework,它是很多模塊的集合,使用這些模塊可以很方便地協助我們進行開發。這些模塊是:核心容器、數據訪問/集成、Web、AOP(面向切面編程)、工具、消息和測試模塊。比如:Core Container 中的 Core 組件是Spring 所有組件的核心,Beans 組件和 Context 組件是實現IOC和依賴注入的基礎,AOP組件用來實現面向切面編程。

Spring 官網列出的 Spring 的 6 個特徵:

核心技術 :依賴注入(DI),AOP,事件(events),資源,i18n,驗證,數據綁定,類型轉換,SpEL。
測試 :模擬對象,TestContext框架,Spring MVC 測試,WebTestClient。
數據訪問 :事務,DAO支持,JDBC,ORM,編組XML。
Web支持 : Spring MVC和Spring WebFlux Web框架。
集成 :遠程處理,JMS,JCA,JMX,電子郵件,任務,調度,緩存。
語言 :Kotlin,Groovy,動態語言。

(4)列舉一些重要的Spring模塊

下圖對應的是 Spring4.x 版本。目前最新的5.x版本中 Web 模塊的 Portlet 組件已經被廢棄掉,同時增加了用於異步響應式處理的 WebFlux 組件。

Spring Core: 基礎,可以說 Spring 其他所有的功能都需要依賴於該類庫。主要提供 IOC 依賴注入功能。
Spring Aspects:該模塊爲與AspectJ的集成提供支持。
Spring AOP:提供了面向方面的編程實現。
Spring JDBC: Java數據庫連接。
Spring JMS:Java消息服務。
Spring ORM: 用於支持Hibernate等ORM工具。
Spring Web: 爲創建Web應用程序提供支持。
Spring Test: 提供了對 JUnit 和 TestNG 測試的支持。

(5)談談自己對於 Spring IoC 和 AOP 的理解

IoC:

IoC(Inverse of Control:控制反轉)是一種設計思想,就是 將原本在程序中手動創建對象的控制權,交由Spring框架來管理。 IoC 在其他語言中也有應用,並非 Spirng 特有。 IoC 容器是 Spring 用來實現 IoC 的載體, IoC 容器實際上就是個Map(key,value),Map 中存放的是各種對象。
將對象之間的相互依賴關係交給 IOC 容器來管理,並由 IOC 容器完成對象的注入。這樣可以很大程度上簡化應用的開發,把應用從複雜的依賴關係中解放出來。 IOC 容器就像是一個工廠一樣,當我們需要創建一個對象的時候,只需要配置好配置文件/註解即可,完全不用考慮對象是如何被創建出來的。 在實際項目中一個 Service 類可能有幾百甚至上千個類作爲它的底層,假如我們需要實例化這個 Service,你可能要每次都要搞清這個 Service 所有底層類的構造函數,這可能會把人逼瘋。如果利用 IOC 的話,你只需要配置好,然後在需要的地方引用就行了,這大大增加了項目的可維護性且降低了開發難度。

Spring 時代我們一般通過 XML 文件來配置 Bean,後來開發人員覺得 XML 文件來配置不太好,於是 SpringBoot 註解配置就慢慢開始流行起來。
推薦閱讀:https://www.zhihu.com/question/23277575/answer/169698662
Spring IOC的初始化過程:

IOC源碼閱讀
https://javadoop.com/post/spring-ioc

AOP

AOP(Aspect-Oriented Programming:面向切面編程)能夠將那些與業務無關,卻爲業務模塊所共同調用的邏輯或責任(例如事務處理、日誌管理、權限控制等)封裝起來,便於減少系統的重複代碼,降低模塊間的耦合度,並有利於未來的可拓展性和可維護性。
Spring AOP就是基於動態代理的,如果要代理的對象,實現了某個接口,那麼Spring AOP會使用JDK Proxy,去創建代理對象,而對於沒有實現接口的對象,就無法使用 JDK Proxy 去進行代理了,這時候Spring AOP會使用Cglib ,這時候Spring AOP會使用 Cglib 生成一個被代理對象的子類來作爲代理,如下圖所示:

Spring AOP Process

當然你也可以使用 AspectJ ,Spring AOP 已經集成了AspectJ ,AspectJ 應該算的上是 Java 生態系統中最完整的 AOP 框架了。
使用 AOP 之後我們可以把一些通用功能抽象出來,在需要用到的地方直接使用即可,這樣大大簡化了代碼量。我們需要增加新功能時也方便,這樣也提高了系統擴展性。日誌功能、事務管理等等場景都用到了 AOP 。

 

(6)Spring AOP 和 AspectJ AOP 有什麼區別?

Spring AOP 屬於運行時增強,而 AspectJ 是編譯時增強。 Spring AOP 基於代理(Proxying),而 AspectJ 基於字節碼操作(Bytecode Manipulation)。
Spring AOP 已經集成了 AspectJ ,AspectJ 應該算的上是 Java 生態系統中最完整的 AOP 框架了。AspectJ 相比於 Spring AOP 功能更加強大,但是 Spring AOP 相對來說更簡單,
如果我們的切面比較少,那麼兩者性能差異不大。但是,當切面太多的話,最好選擇 AspectJ ,它比Spring AOP 快很多。

 

(7)Spring 中的 bean 的作用域有哪些?

singleton : 唯一 bean 實例,Spring 中的 bean 默認都是單例的。

prototype : 每次請求都會創建一個新的 bean 實例。

request : 每一次HTTP請求都會產生一個新的bean,該bean僅在當前HTTP request內有效。

session : 每一次HTTP請求都會產生一個新的 bean,該bean僅在當前 HTTP session 內有效。

global-session: 全局session作用域,僅僅在基於portlet的web應用中才有意義,Spring5已經沒有了。Portlet是能夠生成語義代碼(例如:HTML)片段的小型Java Web插件。它們基於portlet容器,可以像servlet一樣處理HTTP請求。但是,與 servlet 不同,每個 portlet 都有不同的會話。

 

(8)Spring 中的單例 bean 的線程安全問題了解嗎?

大部分時候我們並沒有在系統中使用多線程,所以很少有人會關注這個問題。單例 bean 存在線程問題,主要是因爲當多個線程操作同一個對象的時候,對這個對象的非靜態成員變量的寫操作會存在線程安全問題。

常見的有兩種解決辦法:

在Bean對象中儘量避免定義可變的成員變量(不太現實)。

在類中定義一個ThreadLocal成員變量,將需要的可變成員變量保存在 ThreadLocal 中(推薦的一種方式)。

 

(9)Spring 中的 bean 生命週期?

這部分網上有很多文章都講到了,下面的內容整理自:https://yemengying.com/2016/07/14/spring-bean-life-cycle/
除了這篇文章,再推薦一篇很不錯的文章 :https://www.cnblogs.com/zrtqsk/p/3735273.html

Bean 容器找到配置文件中 Spring Bean 的定義。

Bean 容器利用 Java Reflection API 創建一個Bean的實例。

如果涉及到一些屬性值 利用 set()方法設置一些屬性值。

如果 Bean 實現了 BeanNameAware 接口,調用 setBeanName()方法,傳入Bean的名字。

如果 Bean 實現了 BeanClassLoaderAware 接口,調用 setBeanClassLoader()方法,傳入 ClassLoader對象的實例。

如果Bean實現了 BeanFactoryAware 接口,調用 setBeanClassLoader()方法,傳入 ClassLoade r對象的實例。

與上面的類似,如果實現了其他 *.Aware接口,就調用相應的方法。

如果有和加載這個 Bean 的 Spring 容器相關的 BeanPostProcessor 對象,執行postProcessBeforeInitialization() 方法

如果Bean實現了InitializingBean接口,執行afterPropertiesSet()方法。

如果 Bean 在配置文件中的定義包含 init-method 屬性,執行指定的方法。

如果有和加載這個 Bean的 Spring 容器相關的 BeanPostProcessor 對象,執行postProcessAfterInitialization() 方法

當要銷燬 Bean 的時候,如果 Bean 實現了 DisposableBean 接口,執行 destroy() 方法。

當要銷燬 Bean 的時候,如果 Bean 在配置文件中的定義包含 destroy-method 屬性,執行指定的方法。

Spring Bean 生命週期

與之比較類似的中文版本:

 

(10)Spring 框架中用到了哪些設計模式?

工廠設計模式 : Spring使用工廠模式通過 BeanFactory、ApplicationContext 創建 bean 對象。

代理設計模式 : Spring AOP 功能的實現。

單例設計模式 : Spring 中的 Bean 默認都是單例的。

模板方法模式 : Spring 中 jdbcTemplate、hibernateTemplate 等以 Template 結尾的對數據庫操作的類,它們就使用到了模板模式。

包裝器設計模式 : 我們的項目需要連接多個數據庫,而且不同的客戶在每次訪問中根據需要會去訪問不同的數據庫。這種模式讓我們可以根據客戶的需求能夠動態切換不同的數據源。

觀察者模式 : Spring 事件驅動模型就是觀察者模式很經典的一個應用。

適配器模式 : Spring AOP 的增強或通知(Advice)使用到了適配器模式、spring MVC 中也是用到了適配器模式適配Controller。

等等

 

(11)@Component 和 @Bean 的區別是什麼?

作用對象不同: @Component 註解作用於類,而@Bean註解作用於方法。

@Component通常是通過類路徑掃描來自動偵測以及自動裝配到Spring容器中(我們可以使用 @ComponentScan 註解定義要掃描的路徑從中找出標識了需要裝配的類自動裝配到 Spring 的 bean 容器中)。@Bean 註解通常是我們在標有該註解的方法中定義產生這個 bean,@Bean告訴了Spring這是某個類的示例,當我需要用它的時候還給我。

@Bean 註解比 Component 註解的自定義性更強,而且很多地方我們只能通過 @Bean 註解來註冊bean。比如當我們引用第三方庫中的類需要裝配到 Spring容器時,則只能通過 @Bean來實現。

(12)將一個類聲明爲Spring的 bean 的註解有哪些?

我們一般使用 @Autowired 註解自動裝配 bean,要想把類標識成可用於 @Autowired註解自動裝配的 bean 的類,採用以下註解可實現:

@Component :通用的註解,可標註任意類爲 Spring 組件。如果一個Bean不知道屬於拿個層,可以使用@Component 註解標註。

@Repository : 對應持久層即 Dao 層,主要用於數據庫相關操作。

@Service : 對應服務層,主要涉及一些複雜的邏輯,需要用到 Dao層。

@Controller : 對應 Spring MVC 控制層,主要用戶接受用戶請求並調用 Service 層返回數據給前端頁面

 

(13)Spring 管理事務的方式有幾種?

編程式事務,在代碼中硬編碼。(不推薦使用)

聲明式事務,在配置文件中配置(推薦使用)

聲明式事務又分爲兩種:

基於XML的聲明式事務

基於註解的聲明式事務

 

(14)Spring 事務中的隔離級別有哪幾種?

TransactionDefinition 接口中定義了五個表示隔離級別的常量:

TransactionDefinition.ISOLATION_DEFAULT: 使用後端數據庫默認的隔離級別,Mysql 默認採用的 REPEATABLE_READ隔離級別 Oracle 默認採用的 READ_COMMITTED隔離級別.

TransactionDefinition.ISOLATION_READ_UNCOMMITTED: 最低的隔離級別,允許讀取尚未提交的數據變更,可能會導致髒讀、幻讀或不可重複讀

TransactionDefinition.ISOLATION_READ_COMMITTED: 允許讀取併發事務已經提交的數據,可以阻止髒讀,但是幻讀或不可重複讀仍有可能發生

TransactionDefinition.ISOLATION_REPEATABLE_READ: 對同一字段的多次讀取結果都是一致的,除非數據是被本身事務自己所修改,可以阻止髒讀和不可重複讀,但幻讀仍有可能發生。

TransactionDefinition.ISOLATION_SERIALIZABLE: 最高的隔離級別,完全服從ACID的隔離級別。所有的事務依次逐個執行,這樣事務之間就完全不可能產生干擾,也就是說,該級別可以防止髒讀、不可重複讀以及幻讀。但是這將嚴重影響程序的性能。通常情況下也不會用到該級別。

 

(15)Spring 事務中哪幾種事務傳播行爲?

支持當前事務的情況:

TransactionDefinition.PROPAGATION_REQUIRED: 如果當前存在事務,則加入該事務;如果當前沒有事務,則創建一個新的事務。

TransactionDefinition.PROPAGATION_SUPPORTS: 如果當前存在事務,則加入該事務;如果當前沒有事務,則以非事務的方式繼續運行。

TransactionDefinition.PROPAGATION_MANDATORY: 如果當前存在事務,則加入該事務;如果當前沒有事務,則拋出異常。(mandatory:強制性)

不支持當前事務的情況:

TransactionDefinition.PROPAGATION_REQUIRES_NEW: 創建一個新的事務,如果當前存在事務,則把當前事務掛起。

TransactionDefinition.PROPAGATION_NOT_SUPPORTED: 以非事務方式運行,如果當前存在事務,則把當前事務掛起。

TransactionDefinition.PROPAGATION_NEVER: 以非事務方式運行,如果當前存在事務,則拋出異常。

其他情況:

TransactionDefinition.PROPAGATION_NESTED: 如果當前存在事務,則創建一個事務作爲當前事務的嵌套事務來運行;如果當前沒有事務,則該取值等價於TransactionDefinition.PROPAGATION_REQUIRED。

 

(16)什麼是Spring?

Spring是一個輕量級的容器,他實現了IOC和非侵入的框架,並提供了AOP的實現方式,提供了持久層事務的支持,其讓Java開發模塊化,並且貫穿持久層、邏輯層、表現層,讓每一個模塊都可以獨立分開,降低耦合,提高代碼複用率。

 

(17)Spring的好處

Spring提供了IOC和DI,將管理和維護對象的工作交給了Spring

Spring比較輕量級

Spring並不排斥其他框架,所以其他框架和Spring整合變得很容易

Spring提供了SpringMVC

Spring提供了便捷的事務控制

 

(18)SpringIOC和DI

IOC是將維護對象和創建對象的工作交給Spring,而不用我們自己去創建和維護

DI是注入對象中所需要的屬性

 

(19)DI的三種方式

構造方法

set方法

接口

(20)BeanFactory 和ApplicationContext的區別

(1)首先BeanFactory和ApplicationContext都是接口,並且ApplicationContext是BeanFactory的子接口。

(2)其次BeanFactory是Spring中最底層的接口,提供了最簡單的容器的功能,只提供了實例化對象和拿對象的功能

(3)ApplicationContext(應用上下文)是Spring的一個更高級的容器,提供了更多的有用的功能,ApplicationContext繼承了BeanFactory接口,所以,ApplicationContext也能像BeanFactory從容器中得到Bean(繼承至 ListableBeanFactory).

(4)加載方式不同,BeanFactory採用的是延遲加載的形式來注入Bean,即只有在使用某個bean的時候,纔對該Bean進行加載實例化。

(5)ApplicationContext則相反的,它是在Ioc容易啓動時就一次性創建所有的Bean,

 

(21)常見的ApplicationContext的實現方式

ClassPathXmlApplicationContext

FileSystemXmlApplicationContext

XmlWebApplicationContext

 

(22)SpringBean的作用域?

https://blog.csdn.net/fuzhongmin05/article/details/73389779

https://blog.csdn.net/kongmin_123/article/details/82048392

(23)Spring事件(5種)

上下文更新事件(ContextRefreshedEvent):該事件會在ApplicationContext被初始化或者更新時發佈,也可以在調用ConfigurableApplicationContext接口中的refresh()方法時被觸發。

上下文開始事件(ContextStartedEvent): 當容器調用ConfigurableApplicationContext的Start()方法開始/重新開始容器時被觸發。

上下文停止事件(ContextStoppedEvent): 當容器調用ConfigurableApplicationContext的Stop()方法停止容器時觸發該事件。

上下文關閉事件(ContextClosedEvent): 當ApplicationContext被關閉時觸發該事件。容器被關閉時,其管理的所有單例Bean都被銷燬。

請求處理事件(RequestHandledEvent): 在Web應用中,當一個http請求(request)結束觸發該事件。

允許用戶自定義事件,繼承ApplicationEvent,並且還要創建一個監聽器

 

(24)Spring用到了那些設計模式

代理模式—在AOP和remoting中被用的比較多。

單例模式—在spring配置文件中定義的bean默認爲單例模式

模板方法—用來解決代碼重複的問題。

前端控制器—Spring提供了DispatcherServlet來對請求進行分發。

工廠模式—BeanFactory用來創建對象的實例。

依賴注入—貫穿於BeanFactory / ApplicationContext接口的核心理念。

(25)什麼是aop?

將通用的代碼從業務中分離出來,簡化代碼。使用的爲jdk代理和cglib代理

連接點 : 在方法的執行前後和拋出異常可以作爲連接點,即將增強和目標方法連接的地方。

切入點 : 在某個方法被調用的時候,這個方法上的連接點變爲切入點

增強 : 目標方法除了核心業務以外的所需要的方法, 比如在save()方法中,save()爲核心方法,開啓事務爲非核心方法,可以抽離出來, 在AOP中開啓事務就叫做增強

切面 : 除了目標方法所在的類以外其他的類

代理 : 將目標方法和增強結合在一起

織入 : 生成代理類的過程

 

參考:

http://www.springmvc.cn/archives/22.html

http://www.springmvc.cn/category/spring/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章