寫在前面:繼續看看spring的面試題,打開ThinkWon大神的總結,不禁吸了兩口真氣,由於是初學者,很多知識點沒有學到,這邊只記錄學到的,並且能理解的,部分加入自己的想法,一些不能理解的問題應該深入學習後再來補充。
原文鏈接:https://blog.csdn.net/ThinkWon/article/details/104397516
目錄
- 1. spring 概述部分
- 1.1 什麼是spring?
- 1.2 spring框架的核心?
- 1.3 spring框架的優缺點
- 1.4 spring5 的主要模塊構成
- 1.5 Spring 框架中都用到了哪些設計模式?
- 1.6 講解一下核心容器(spring context應用上下文) 模塊
- 2. spring的控制反轉(IOC)
- 2.1 什麼是Spring IOC 容器?
- 2.2 IOC 有什麼作用?
- 2.3 使用IOC容器的優點?
- 2.4 spring IOC支持哪些功能
- 2.5 BeanFactory 和 ApplicationContext有什麼區別?
- 2.6 ApplicationContext通常的實現是什麼?
- 2.8 什麼是Spring的依賴注入?
- 2.9 依賴注入有什麼優勢?
- 2.10 有哪些不同類型的依賴注入實現方式?
- 2.11 構造器依賴注入和Setter方法注入的區別
- 3. spring 的 Bean
- 3.1 什麼是Spring bean?
- 3.2 一個 Spring Bean 定義 包含什麼?
- 3.3 如何給Spring 容器提供配置元數據?Spring有幾種配置方式
- 3.4 Spring基於xml注入bean的幾種方式
- 3.5 你怎樣定義類的作用域?
- 3.6 解釋Spring支持的幾種bean的作用域?
- 3.7 Spring框架中的單例bean是線程安全的嗎?
- 3.8 Spring如何處理多線程併發問題?
- 3.9 使用@Autowired註解自動裝配的過程是怎樣的?
- 3.10 你可以在Spring中注入一個null 和一個空字符串嗎?
- 4. spring的常用註解
- 4.1 什麼是基於Java的Spring註解配置? 給一些註解的例子
- 4.2 怎樣開啓註解裝配?
- 4.3 @Component, @Controller, @Repository, @Service 有何區別?
- 4.4 @Required 註解有什麼作用
- 4.5 @Autowired 註解有什麼作用
- 4.6 @Autowired和@Resource之間的區別
- 4.7 @Qualifier 註解有什麼作用
- 4.8 @RequestMapping 註解有什麼用?
- 5. spring的數據訪問
- 5.1 JdbcTemplate是什麼
- 5.2 Spring支持的事務管理類型, spring 事務實現方式有哪些?
- 5.3 說一下Spring的事務傳播行爲
- 5.4 說一下 spring 的事務隔離?
- 5.5 Spring框架的事務管理有哪些優點?
- 5.6 Spring框架的事務管理有哪些優點?
- 6. spring的面向切面編程(AOP)
1. spring 概述部分
1.1 什麼是spring?
spring是一個輕量級
的JavaEE開源框架,開發spring的根本使命目的是爲了企業應用開發的複雜性,即簡化Java開發。
spring的兩個核心特性:控制反轉和麪向切面編程,即IOC和AOP。
spring 的特點:
- 輕量:從大小和開銷方面而言spring都是輕量的,處理開銷也是微不足道的。
- IOC:削減計算機之間的耦合,降低程序代碼中的依賴關係。
- AOP:通過配置管理特性spring的AOP,可以將一些通用的任務,如安全,事務,日誌等集中進行管理,提高了程序的複用性和管理型。
- 容器:Spring提供了容器功能,容器可以管理對象的生命週期、對象與對象間的關係、我們可以通過編寫XML來設置對象關係和初始值,這樣容器在啓動之後,所有的對象都直接可以使用,不用編寫任何編碼來產生對象。Spring有兩種不同的容器:Bean工廠以及應用上下文。
- 框架:可以將簡單的組件配置,組成複雜的應用,spring也提供了很多基礎功能(事務管理,持久化框架集成)將應用邏輯留給開發者。
1.2 spring框架的核心?
IOC和AOP模塊。通過IOC容器管理POJO或JavaBean對象,以及它們之間的耦合關係;通過AOP以動態非入侵的方式增強服務。
1.3 spring框架的優缺點
優點
- 方便解耦,簡化開發
Spring就是一個大工廠,可以將所有對象的創建和依賴關係的維護(DI),交給Spring管理。
- AOP編程的支持
Spring提供面向切面編程,可以方便的實現對程序進行權限攔截、運行監控和增強等功能。
- 聲明式事務的支持
只需要通過配置就可以完成對事務的管理,而無需手動編程。
- 方便程序的測試
Spring對Junit4支持,可以通過註解方便的測試Spring程序。
- 方便集成各種優秀框架
Spring不排斥各種優秀的開源框架,其內部提供了對各種優秀框架的直接支持(如:Struts、Hibernate、MyBatis等)。
- 降低JavaEE API的使用難度
Spring對JavaEE開發中非常難用的一些API(JDBC、JavaMail、遠程調用等),都提供了封裝,使這些API應用難度大大降低。
缺點
- Spring明明一個很輕量級的框架,卻給人感覺大而全,內容太龐大。
- Spring依賴反射,反射影響性能
- 使用門檻升高,入門Spring需要較長時間
1.4 spring5 的主要模塊構成
Spring 總共大約有 20 個模塊, 由 1300 多個不同的文件構成。 而這些組件被分別整合在核心容器(Core Container) 、 AOP(Aspect Oriented Programming)和設備支持(Instrmentation) 、數據訪問與集成(Data Access/Integeration) 、 Web、 消息(Messaging) 、 Test等 6 個模塊中。 以下是 Spring 5 的模塊結構圖
- spring core:提供了框架的基本組成部分,包括控制反轉(Inversion of Control,IOC)和依賴注入(Dependency Injection,DI)功能。
- spring beans:提供了BeanFactory,是工廠模式的一個經典實現,Spring將管理對象稱爲Bean。
- spring context:構建於 core 封裝包基礎上的 context 封裝包,提供了一種框架式的對象訪問方法。
- spring jdbc:提供了一個JDBC的抽象層,消除了煩瑣的JDBC編碼和數據庫廠商特有的錯誤代碼解析, 用於簡化JDBC。
- spring aop:提供了面向切面的編程實現,讓你可以自定義攔截器、切點等。
- spring Web:提供了針對 Web 開發的集成特性,例如文件上傳,利用 servlet listeners - 進行 ioc 容器初始化和針對 Web 的 ApplicationContext。
- spring test:主要爲測試提供支持的,支持使用JUnit或TestNG對Spring組件進行單元測試和集成測試。
1.5 Spring 框架中都用到了哪些設計模式?
- 工廠模式:BeanFactory就是簡單工廠模式的體現,用來創建對象的實例;
- 單例模式:Bean默認爲單例模式。
- 代理模式:Spring的AOP功能用到了JDK的動態代理和CGLIB字節碼生成技術;
- 模板方法:用來解決代碼重複的問題。比如. RestTemplate, JmsTemplate, JpaTemplate。
1.6 講解一下核心容器(spring context應用上下文) 模塊
應用上下文模塊是spring框架的基本模塊,BeanFactory是任何以spring爲基礎的應用的核心,spring框架建立在context這個模塊上,使得spring成爲一個容器。
Bean工廠是工廠模式的一個實現,提供了控制反轉的功能。用來把應用的配置和依賴真正從代碼中分離出來。最常用的是根據xml文件加載bean對象進IOC容器中,使得的類是ApplicationContext的實現類org.springframework.beans.factory.xml.XmlBeanFactory。
2. spring的控制反轉(IOC)
2.1 什麼是Spring IOC 容器?
所謂控制反轉主要是把傳統上的程序直接向內存中申請空間創建對象的這個控制權轉移到了外部工廠,通過工廠來對這些創建好的對象進行裝配和管理。外部工廠即我們常說的IOC容器,spring IOC負責創建對象,管理對象(依賴注入,裝配對象Autowride)並管理這些對象的整個生命週期。
2.2 IOC 有什麼作用?
- 管理對象的創建和依賴關係的維護。
- 解耦降低了依賴,由容器去維護具體的對象的創建。
- bean對象生命週期管理。
2.3 使用IOC容器的優點?
- IOC和DI的配合使用能把應用的實際代碼量降到最低。
- spring集成了自己的測試模塊,無需依賴於junit。
- IOC容器支持立即加載和延遲加載(懶加載)。
2.4 spring IOC支持哪些功能
- 依賴注入
- 依賴檢查
- 自動裝配
- 支持集合
2.5 BeanFactory 和 ApplicationContext有什麼區別?
BeanFactory 和 ApplicationContext都是spring的兩個核心的接口,都可以當作容器來使用,其中BeanFactory是ApplicationContext父接口。它們之間的區別由:
依賴關係
:BeanFactory是spring中最底層的接口,包含了各種bean的定義,讀取bean的配置文檔,管理bean的加載,實例化,控制bean生命週期,維護bean之間的依賴關係。
而ApplicationContext作爲BeanFactory 的子接口,除了BeanFactory本身的功能外,提供了更加完善的框架功能。如:
- 繼承MessageSource,因此支持國際化。
- 統一資源文件的訪問方式
- 同時加載多個配置文件
- 提供監聽器中註冊bean的事件
加載方式
:BeanFactory採用的是延遲加載的方式,即當我們要使用bean時調用getBean方法開始實例化bean對象。如此我們容易遇到就是在配置文件中忘記配置bean(未注入),而去調用它的getBean對象,將會拋出異常。
ApplicationContext是在容器啓動後,創建所有的bean,比起BeanFactory的加載方式,採用ApplicationContext的加載更容易發現spring配置中的問題,有利於檢查依賴是否注入,加載出來的單例bean對象,可以直接拿去用而不用等待。
創建方式
:BeanFactory通常以編程的形式被創建,而ApplicationContext還能以聲明的形式被創建,如ContextLoader.
2.6 ApplicationContext通常的實現是什麼?
- ClassPathXmlApplicationContext:此容器從xml中加載beans的定義,將在classpath中尋找bean的定義。
- FileSystemXmlApplication:和ClassPathXmlApplicationContext類似從xml中加載beans的定義,但是範圍可以時硬盤上的任意位置,只要有訪問權限。
- AnnotationConfigApplicationContext:用於讀取註解創建容器。
2.8 什麼是Spring的依賴注入?
依賴關係的維護又稱爲依賴注入,這種關係交給spring來管理,當我們在類中要用到其它的類對象,都由spring來提供,我們只需要在配置文件中說明即可,依賴注入也是IOC控制反轉的一種實現。
2.9 依賴注入有什麼優勢?
依賴注入之所以流行,是因爲它是一種很可取的方式:讓r容器全權負責依賴的查詢,需要注入的bean對象只需要暴露出JavaBean的setter方法或者帶參數的構造函數,使得容器在初始化時組裝對象依賴關係。與其依賴查找方式相比,主要的優勢有:
- 查找定位操作與應用代碼無關
- 不依賴於容器的API,可以很容易地在任何容器以外使用應用對象。
- 不需要特殊的接口,絕大多數對象可以做到完全不必依賴容器。
2.10 有哪些不同類型的依賴注入實現方式?
依賴注入是時下最流行的IOC控制反轉的一種實現,實現方式有接口注入,構造器注入,setter方法注入。其中由於接口注入的靈活性太差,於是與spring4被廢棄。
構造器依賴注入:構造器依賴注入通過容器觸發一個類的構造器來實現的,該類有一系列參數,每個參數代表一個對其他類的依賴。
Setter方法注入:Setter方法注入是容器通過調用無參構造器或無參static工廠 方法實例化bean之後,調用該bean的setter方法,即實現了基於setter的依賴注入。
2.11 構造器依賴注入和Setter方法注入的區別
構造器依賴注入 | Setter方法注入 |
---|---|
沒有部分注入 | 有部分注入(提供setter) |
不會覆蓋setter屬性 | 會覆蓋setter屬性 |
任意修改都會創建新的實例 | 任意修改都不會創建新的實例 |
適用於設置很多屬性 | 適用於設置少量屬性 |
3. spring 的 Bean
3.1 什麼是Spring bean?
spring Bean是收到spring管理的bean對象,具體來說是被spring容器初始化,配置和管理的對象。spring Bean是再spring配置文件中定義的,現在也可以通過註解來定義,在spring容器初始化,注入到spring應用程序中。
3.2 一個 Spring Bean 定義 包含什麼?
一個spring Bean的定義包含容器所必知道的配置元數據,包括如何創建一個bean,它的生命週期和它的依賴。
3.3 如何給Spring 容器提供配置元數據?Spring有幾種配置方式
有三種配置方式
- 基於XML
- 基於註解配置
- 基於Java配置
前面兩個比較常用。
3.4 Spring基於xml注入bean的幾種方式
- setter方法注入
- 構造函數注入 ,配置index 參數位置和type參數類型
- 靜態工廠注入
- 實例工廠
3.5 你怎樣定義類的作用域?
如果是基於XML配置可以在bean標籤內配置scope
如果spring需要bean的時候每次創建一個新的bean實例,這個時候應該使用多例,即scope = “prototype”。而如果使用一個bean對象,每次返回的是同一個bean對象,則scope = “singleton”。
基於註解開發同樣有scope屬性支持配置。
3.6 解釋Spring支持的幾種bean的作用域?
spring的bean的作用範圍有5個:
- singleton:默認單例,每個容器中只能有一個bean的實例,單例模式由BeanFactory自身來維護。
- prototype:多例,爲每一個bean創建一個實例,容器中可以存在多個實例。
- request:爲每一個網絡請求建立一個實例,當請求完成後,bean隨之被GC回收。
- session:於request類似,每一個session會話有一個bean實例,當會話結束,bean隨之失效。
- global-session:全局的session,通常用於集羣服務器使用,用於建立集羣服務器的會話,多臺服務器可以共享session域,當只有一臺時,建立的就是session會話。
注意: 缺省的Spring bean 的作用域是Singleton。使用 prototype 作用域需要慎重的思考,因爲頻繁創建和銷燬 bean 會帶來很大的性能開銷。
3.7 Spring框架中的單例bean是線程安全的嗎?
不是線程安全的。
spring框架並沒有對單例bean進行任何的多線程封裝處理。關於單例模式下的線程安全和併發問題需要程序員自己來解決,但是對於service和dao層,通常並不需要多個實例,即沒有可變狀態,所以默認情況下時我們說單例時線程安全的。如果你的bean有可變狀態,如Model View對象,就需要自行保證線程的安全,最直接的方法就是修改bean的作用域scope從singleton改爲prototype。
- 有狀態就是有數據存儲功能
- 無狀態就是不會保存數據
3.8 Spring如何處理多線程併發問題?
多線程併發問題的根本在於相同的變量訪問衝突問題。
通常,只有無狀態的bean纔可以再多線程中共享,因爲它們不會導致訪問的衝突情況,spring中可以將絕大部分的bean對象聲明爲singleton。
但是還有一些有狀態的bean爲什麼可以在多線程中共享,如(RequestContextHolder、TransactionSynchronizationManager、LocaleContextHolder等),因爲它們採用了ThreadLocal進行處理,讓它們也成爲線程安全的狀態,所以有狀態的bean就可以在多線程中共享了。
ThreadLocal 和 線程同步機制都是爲了解決相同的變量訪問衝突問題。
線程同步機制中的處理是通過加入對象鎖處理,而ThreadLocal會爲每個線程提供一個獨立的變量副本,從而隔離了多線程數據的衝突訪問,因爲每個變量都有了自己的副本了,也就沒必要對該變量進行數據同步了。ThreadLocal提供線程安全的共享對象,編寫代碼時,可以把哪些不安全的變量封裝進ThreadLocal。
概括來說:
同步機制提供的是一種時間換空間的機制,多個線程只提供一個變量,讓不同線程進行排隊,避免了衝突的發生。
ThreadLocal採用的是一種空間換時間的方式,爲每個線程都提供一個變量,因此可以同時訪問而互不影響。
3.9 使用@Autowired註解自動裝配的過程是怎樣的?
使用@Autowired自動裝配指定bean之前,需要在spring配置文件中進行以下配置。
<context:annotation-config/>
當啓動spring的IOC容器後,容器自動裝載了一個AutowiredAnnotationBeanPostProcessor後置處理器,當容器掃描到@Autowired,@Resources,@Inject時,就會在IOC容器中查詢需要的bean,並裝配給該對象的屬性。在使用@Autowired會在容器中尋找對應類型的bean:
由於容器類似一個一個Map結構,存儲着key-value,查詢機制是先從value上面找
- 如果找到一個,則就將bean裝配給@Autowired指定的數據
- 如果找到兩個,那麼就從key值上面再找,找到則裝配
- 如果查詢結果爲空,則會拋出異常。解決方法,可以設置@Autowired的required的屬性爲false.
3.10 你可以在Spring中注入一個null 和一個空字符串嗎?
可以的。
4. spring的常用註解
4.1 什麼是基於Java的Spring註解配置? 給一些註解的例子
spring註解配置可以替換XML的配置,可以大大減少XML配置的代碼量。
@Configuration:表示這是一個配置類,可以用來爲IOC容器注入bean
@Bean:一般使用在配置類中,用於方法上面,將方法的返回值注入到IOC容器中,默認屬性id爲方法名。
4.2 怎樣開啓註解裝配?
註解裝配默認情況下是不開啓的,如若開啓,spring的XML文件中配置:
<context:annnotation-config/>
4.3 @Component, @Controller, @Repository, @Service 有何區別?
@Component:在類上加載此註解,可以將Java類標記bean,由spring來管理它。spring的組件掃描機制可以可以將其拾取並注入到應用程序環境中(IOC容器)。
@Controller,@Repository,@Service服務於web三層架構,分別是springMVC層,持久層,業務層,功能和@Component一樣,爲什麼有這三個註解,因爲它們更好的指明瞭使用意圖。
4.4 @Required 註解有什麼作用
@Required是爲了保證對應的屬性必須設置,@Required註釋用於bean屬性的setter方法,被它修飾的setter方法對應的屬性必須在XML文件中注入,否則會拋出BeanInitializationException
示例:https://www.cnblogs.com/Guhongying/p/10598732.html
4.5 @Autowired 註解有什麼作用
@Autowired是默認按照類型注入的,默認情況下它要求依賴必須存在,當然可以設置屬性required爲false,它的用法和required類似,可以作用域,屬性,方法構造器或具有任意名稱或任意參數的方法。
4.6 @Autowired和@Resource之間的區別
@Autowired:是默認按照類型注入的,默認情況下它要求依賴必須存在,當然可以設置屬性required爲false。
@Resource:默認是按照名稱注入的,如果找不到名稱匹配的bean,纔會按照類型注入。
4.7 @Qualifier 註解有什麼作用
用於指定bean名稱的註解,和@Autowired配合使用,避免@Autowired因爲找不到類型匹配的bean而拋出異常;或者找到多個bean用名稱來消除歧義匹配唯一bean。
4.8 @RequestMapping 註解有什麼用?
@RequestMapping用於接收HTTP請求,並將請求發送到相應的控制器類/方法上。作用位置有:
- 類:映射請求的URL父級目錄
- 方法:映射URL和HTTP請求方法
5. spring的數據訪問
5.1 JdbcTemplate是什麼
JdbcTemplate是一個封裝了JDBC規範的工具類,並且提供了很多遍歷的方法,如執行寫好或者可調用的SQL語句,提供把數據庫的數據封裝成基本數據類型或對象,提供自定義的數據錯誤處理。
5.2 Spring支持的事務管理類型, spring 事務實現方式有哪些?
spring支持兩種事務的管理方案:
**編程式事務管理:**這意味着通過編程的方式管理事務,給你帶來極大的靈活性,但是難以維護。
**聲明式事務管理:**可以將業務和事務管理分開,你只需要用註解或XML配置來管理事務。
5.3 說一下Spring的事務傳播行爲
事務傳播行爲指的是當存在多個事務時,spring是如何管理這些事務的
可以在配置事務通知中配置事務屬性,propagation裏面有不同的取值
1. PROPAGATION_REQUIRED:如果當前沒有事務,就創建一個新的事務,如果當前有事務,就加入該事務,常用於增刪改,也是最常用的傳播行爲。
2. PROPAGATION_SUPPORTS:支持當前事務,如果當前有事務,就加入該事務,如果沒有事務,就以非事務執行。
------上面兩種比較常見
3. PROPAGATION_MANDATORY:支持當前事務,如果當前有事務,就加入該事務,如果沒有事務,就拋出異常。
4. PROPAGATION_REQUIRES_NEW:創建新事物,無論當前是否存在事務,都創建新事物。
5. PROPAGATION_NOT_SUPPORTED:以非事務方式執行操作,如果當前存在事務,就把事務掛起。
6. PROPAGATION_NOT_SUPPORTED:以非事務方式執行操作,如果當前存在事務,就拋出異常。
7. PROPAGATION_NESTED:如果當前存在事務,就在嵌套事務內執行,如果沒有存在事務,就按照REQUIRED屬性執行。
5.4 說一下 spring 的事務隔離?
spring有5大事務隔離級別,默認值爲isolation = “default”(使用數據庫設置),其它四個隔離級別和數據庫隔離級別一致:
- default:默認遵從數據庫的隔離級別,數據庫設置什麼我就用什麼。
- read_uncommitted:未提交讀,最低的隔離級別,事務未提交前,可能已經被其它事務讀取到(會出現幻讀,髒讀,不可重複讀)
- read_committed:提交讀,一個事務提交後才能被其它事務讀取到(會出現幻讀,不可重複讀),SQLSevier的默認事務級別
- repeatable_read:可重複讀,保證多次讀取同一個數據時,其值和事務開始時的數據都是一致的,禁止讀取到別的事務未被提交的數據(會出現幻讀),MySQL默認的事務級別。
- serializable:序列化,代價最高最可靠的隔離級別,該隔離級別能防止髒讀,不可重複讀,幻讀。
名詞解釋:
- 髒讀:表示一個事務讀取到另外一個事務未提交的數據。例如:事務甲嘗試插入數據A,當時還沒有提交數據,事務乙就已經查詢到了事務甲的數據A。
- 不可重複讀:表示的是在同一個事務兩次訪問同一個數據可能出現不一樣。例如:事務1訪問了數據A,此時還沒有提交,事務2也訪問了數據A,並修改爲數據接着提交了。此時事務1再次訪問數據就可能出現A或B了。
- 幻讀:所謂幻讀時某一個事務讀取到某個範圍的記錄時,另外一個事務也訪問了該範圍的數據,並且增加了新的數據接着提交了,之前的事務再次讀取到該範圍的數據時,會出現幻行。
MySQL中InnoDB存儲引擎通過多版本併發控制(MVCC)解決了幻讀的問題。
5.5 Spring框架的事務管理有哪些優點?
- 爲不同的事務API,如JTA,JDBC,HIbernate,JPA等提供一種不變的編程模式
- 爲編程式事務管理提供一套簡單的API而不是複雜的事務API
- 支持聲明式事務管理
- 和spring各種數據訪問抽象層很好的集成
5.6 Spring框架的事務管理有哪些優點?
我會選擇spring的聲明式事務管理,因爲它的應用代碼量影響最小,更符合一個輕量級容器的思想。聲明式事務管理要由於編程式事務管理,雖然比編程式事務管理少了一點靈活性(代碼控制事務),還有聲明式事務管理只能作用於方法級別的,而編程式事務管理可以作用於代碼塊級別的。
6. spring的面向切面編程(AOP)
6.1 什麼是AOP
OPP是指面向對象編程,運行開發者定義橫向和縱向的關係,這將導致了大量的重複代碼,不利於各個模塊的重用。
AOP
:面向切面編程,作爲面向對象的補充,用於哪些與業務無關,但卻對多個對象產生公共行爲和邏輯,抽取並封裝成一個可重用模塊。這個模塊被稱爲切面,減少系統中的重複代碼,降低模塊間的耦合度,同時提高了系統間的可維護性,可用於權限認證,日誌,事務處理等。
6.2 Spring AOP and AspectJ AOP 有什麼區別?AOP 有哪些實現方式?
AOP的實現關鍵技術在於代理模式,代理模式又分爲靜態代理和動態代理。
AspectJ AOP 使用的是靜態代理,Spring AOP使用的是動態代理。
- AspectJ是靜態代理的增強,所謂靜態代理就是AOP框架會在編譯階段生成AOP代理類,因此也成爲編譯期增強,它會在編譯期將Aspect(切面)織入到Java字節碼中,運行時候就是增強後的AOP對象
- Spring AOP使用的就是動態代理,所謂動態代理就是AOP框架不會去修改字節碼文件,而是每次運行時在內存中臨時爲方法生成一個AOP對象,這個AOP對象包含目標對象的全部方法,並且在特定切點處做了增強處理,並回調原對象的方法。
6.3 JDK動態代理和CGLIB動態代理的區別
Java動態代理是利用反射機制生成一個實現代理接口的匿名類,在具體方法前調用InvokeHandler來處理。而CGLIB動態代理是利用asm開源包,對代理對象類的class文件加載進來,通過修改其字節碼生成子類來處理。
1. 如果目標對象實現了接口,則默認使用JDK的動態代理實現AOP
2. 如果目標對象使用了,可以強制使用CGLIB實現AOP
3. 如果目標對象沒有實現接口,則必須使用CGLIB,spring會自動在CGLIB和JDK動態代理之間切換
如何強制使用CGLIB實現AOP?
- 添加CGLIB庫,SPRING_HOME/cglib/*.jar
- 在spring配置文件中加入 < aop:aspectj-autoproxy proxy-target-class=“true” />
JDK動態代理和CGLIB動態代理生成字節碼的區別
1. JDK動態代理只能對實現接口的類生成代理,不能針對類
2. CGLIB是針對類實現代理,主要是指定的類生成一個子類,覆蓋其中方法,因爲是繼承,所以該類或方法最好不要聲明爲final
6.4 如何理解 Spring 中的代理?
將Advice應用於目標對象後創建的對象稱爲代理,在客戶端對象情況下,目標對象和代理對象是相同的的。
TargetObject + Advice = Proxy
6.5 解釋一下Spring AOP裏面的幾個名詞
- 切面(Aspect):切面是通知和切點的結合,通知和切點共同定義了切面的全部內容,在spring AOP中在類上加上@AspectJ來實現。
- Joinpoint(連接點):連接點代表這一個個的方法,切面代碼可以通過這些點插入到應用程序的正常流程中,並添加新的行爲。
- Pointcut(切入點):也是代表方法,但是這些方法並沒有被增強。
- Advice(通知/增強):spring AOP攔截到Joinpoint(連接點)所要做增強過程就是通知。
- 引入(Introduction):不修改代碼的前提下,運行期我們新的類中添加新的屬性或方法
- 織入(Weaving):是指把增強應用到目標對象來創建新的代理對象的過程。spring 採用動態代理織入,而 AspectJ 採用編譯期織入和類裝載期織入。簡單的說加入事務控制的過程叫做織入。
- Proxy(代理):一個類被AOP織入增強後,就產生結果代理類,其實就是代理對象。
- Target(目標對象):代理目標對象,就是被代理對象。
6.6 Spring通知有哪些類型?
在AOP屬於中,切面的工作被稱爲通知,實際上是程序執行時要通過spring AOP框架觸發的代碼段。
spring可以又5中通知類型:
- 前置通知(Before):在目標方法被調用之前調用此方法。
- 後置通知(After):在目標方法調用完成後執行。
- 最終通知(After-returning):目標方法成功執行之後執行。
- 異常通知(After-throwing):在目標方法拋出異常後調用通知。
- 環繞通知(Around):通知包裹被通知的方法,在被通知調用之前和調用之後執行自定義的行爲。
但是spring AOP又兩種不一樣的通知執行順序:
1.invoke 方法中沒有異常拋出
1. 前置通知
2. 方法執行
3. 後置通知
3. 最終通知
2.invoke 方法中有異常拋出
1. 前置通知
2. 方法執行
3. 異常通知通知
3. 最終通知
6.7 什麼是切面 Aspect?
Aspect由Advice 和 pointcut組成,切面是通知點和切入點的組合,它既包含了橫切邏輯的定義,也包含了連接點的定義,spring AOP就是負責實現切面的框架,它將切面定義的橫切邏輯編織到切面所定義的連接點中。
AOP的工作重心在於如何將增強編織目標對象的連接點。這裏包含兩個工作:
- 如何通過Advice 和 pointcut定義到特定的jointpoint上
- 如何在advice上編寫代碼
可以簡單的認爲,使用@Aspect註解的類就是一個切面