天天看點

Java常見面試題總結

Java常見面試題總結

@Date 2016.06.22

Java基礎知識

1.Java 中應該使用什麼資料類型來代表價格?

如果不是特别關心記憶體和性能的話,使用BigDecimal,否則使用預定義精度的 double 類型。

2.怎麼将 byte 轉換為String,以及注意點?

可以使用 String 接收 byte[] 參數的構造器來進行轉換,需要注意的點是要使用的正确的編碼,否則會使用平台預設編碼,這個編碼可能跟原來的編碼相同,也可能不同。

3.我們能将 int 強制轉換為 byte 類型的變量嗎?如果該值大于 byte 類型的範圍,将會出現什麼現象?

可以做強制轉換,但是 Java 中 int 是 32 位的,而 byte 是 8 位的,是以,如果強制轉化是,int 類型的高 24 位将會被丢棄,byte 類型的範圍是從 -128 到 128。

4.clone方法在哪個類中?Cloneable 還是 Object?

java.lang.Cloneable 是一個标示性接口,不包含任何方法,clone 方法在 object 類中定義。并且需要知道 clone() 方法是一個本地方法,這意味着它是由 c 或 c++ 或 其他本地語言實作的。

5.Java 中 ++ 操作符是線程安全的嗎?

不是線程安全的操作。它涉及到多個指令,如讀取變量值,增加,然後存儲回記憶體,這個過程可能會出現多個線程交差。

6.a = a + b 與 a += b 的差別?

注意類型強勢轉換的問題

7.為什麼 Java 中的 String 是不可變的?

Java 中的 String 不可變是因為 Java 的設計者認為字元串使用非常頻繁,将字元串設定為不可變可以允許多個用戶端之間共享相同的字元串。

8.final都能修飾什麼,起到什麼作用?

final 是一個修飾符,可以修飾變量、方法和類。如果 final 修飾變量,意味着該變量的值在初始化後不能被改變。

9.什麼是強類型程式設計語言?

在強類型語言中,編譯器確定類型的正确性,例如你無法在String類型中存放數字,反之亦然。Java是強類型語言,是以存在各種資料類型(如int、float、String、char、boolean等)。你隻能将相容的值存入相應的類型中。與此相反,弱類型語言不要求在編譯時進行類型檢查,它們根據上下文處理值。Python和Perl是兩個常見的弱類型程式設計語言的例子,你可以将數字組成的字元串儲存在數字類型中。

10.不可變(immutable)類是什麼意思?

一個類,如果在建立之後它的狀态就不能被改變,那麼他就是不可變的。例如Java中的String。一旦你建立了一個String,例如“Java”,你就不能再改變它的内容。任何對這個字元串的改變(例如轉換到大寫、與另一個String連接配接)将建立一個新的對象。不可變的對象在并行程式設計中很有用,因為它們可以在程序間被共享,不需要擔心同步。事實上,整個函數是程式設計的模型都是在不可變對象上建構的。

11.接口和抽象類有什麼差別?

這是所有程式員面試最經典的問題。接口是最純粹的抽象形式,沒有任何具體的東西。抽象類是一些抽象和具體事物的組合體。這個差別在不同語言中可能會不同,例如在Java中你可以擴充(extend)多個接口,但隻能繼承一個抽象類。

12.疊代和遞歸有什麼差別?

疊代通過循環來重複執行同一步驟,遞歸通過調用函數自身來做重複性工作。遞歸經常是複雜問題(例如漢諾塔、反轉連結清單或反轉字元串)的清晰簡潔的解決方案。遞歸的一個缺陷是深度,由于遞歸在棧中存儲中間結果,你隻能進行一定深度的遞歸,在那之後你的程式會因為StackOverFlowError而崩潰。這就是在産品代碼中優先使用疊代而不是遞歸的原因。

13.&和&&運算符的差別是什麼?

&是位運算符,&&是邏輯運算符。&和&&的一個差別是位運算符(&)可以被用于整型和布爾類型,邏輯運算符(&&)隻能被用于布爾類型變量。當你寫a & b時,兩個整型數的每一位都會進行與運算。當你寫a && b時,第二個參數可能會也可能不會被執行,這也是它被稱為短路運算符的原因,至少在Java中是這樣的。我很喜歡這個問題,經常對初級開發者和畢業生問這個問題。

14.如何得到一個整型數的最後一位?

用取模運算符,數字 % 10傳回數字的最後一位。例如2345 % 10會傳回5,567 % 10會傳回7。類似的,除運算符可以用來去掉數字的最後一位,例如2345 / 10的結果是234,567 / 10的結果是56。這是值得了解的一個重要技巧,可以用來解決類似回文數、反轉數的問題。

15.連結清單和數組有哪些重要差別?

連結清單和數組都是程式設計世界中重要的資料結構。它們間最明顯的差別是,數組将元素存放在連續的位址中,連結清單将資料存放在記憶體中任意的位置。這使得連結清單有巨大的擴充自己的靈活性,因為記憶體總是分散的。這種情況總是可能的:你無法建立一個數組來存放一百萬個整數,但可以用連結清單來存放,因為空間是存在的,隻是不連續。其他的不同都是源于這項事實。例如,在數組中,如果你知道下标,可以用O(1)的時間得到一個元素,但在連結清單中要花O(n)的時間。

16.有沒有可能兩個不相等的對象有有相同的 hashcode?

有可能,兩個不相等的對象可能會有相同的 hashcode 值,這就是為什麼在 hashmap 中會有沖突。相等 hashcode 值的規定隻是說如果兩個對象相等,必須有相同的hashcode 值,但是沒有關于不相等對象的任何規定。

17.兩個相同的對象會有不同的的 hash code 嗎?

不能,根據 hash code 的規定,這是不可能的。

18.我們可以在 hashcode() 中使用随機數字嗎?

不行,因為對象的 hashcode 值必須是相同的。參見答案擷取更多關于 Java 中重寫 hashCode() 方法的知識。

19.為什麼在重寫 equals 方法的時候需要重寫 hashCode 方法?

因為有強制的規範指定需要同時重寫 hashcode 與 equal 是方法,許多容器類,如 HashMap、HashSet 都依賴于 hashcode 與 equals 的規定。

Java集合架構

1.List、Set之間的差別

List 是一個有序集合,允許元素重複。它的某些實作可以提供基于下标值的常量通路時間,但是這不是 List 接口保證的。Set 是一個無序集合。

2.隊列操作poll() 方法和 remove() 方法的差別?

poll() 和 remove() 都是從隊列中取出一個元素,但是 poll() 在擷取元素失敗的時候會傳回空,但是 remove() 失敗的時候會抛出異常。

3.Java 中 LinkedHashMap 和 PriorityQueue 的差別是什麼?

PriorityQueue 保證最高或者最低優先級的的元素總是在隊列頭部,但是 LinkedHashMap 維持的順序是元素插入的順序。當周遊一個 PriorityQueue 時,沒有任何順序保證,但是 LinkedHashMap 課保證周遊順序是元素插入的順序。

4.ArrayList 與 LinkedList 的不差別?

最明顯的差別是 ArrrayList 底層的資料結構是數組,支援随機通路,而 LinkedList 的底層資料結構書連結清單,不支援随機通路。使用下标通路一個元素,ArrayList 的時間複雜度是 O(1),而 LinkedList 是 O(n)。

5.用哪兩種方式來實作集合的排序?

你可以使用有序集合,如 TreeSet 或 TreeMap,你也可以使用有順序的的集合,如 list,然後通過 Collections.sort() 來排序。

6.Java 中的 LinkedList 是單向連結清單還是雙向連結清單?

是雙向連結清單,你可以檢查 JDK 的源碼。

7.Java 中的 TreeMap 是采用什麼樹實作的?

Java 中的 TreeMap 是使用紅黑樹實作的。(紅黑樹的資料結構)

8.Hashtable 與 HashMap 有什麼不同之處?

這兩個類有許多不同的地方,下面列出了一部分:

(1)HashMap允許key和value為null,而HashTable不允許。

(2)HashTable是同步的,而HashMap不是。是以HashMap适合單線程環境,HashTable适合多線程環境。

(3)在Java1.4中引入了LinkedHashMap,HashMap的一個子類,假如你想要周遊順序,你很容易從HashMap轉向LinkedHashMap,但是HashTable不是這樣的,它的順序是不可預知的。

(4)HashMap提供對key的Set進行周遊,是以它是fail-fast的,但HashTable提供對key的Enumeration進行周遊,它不支援fail-fast。

(5)HashTable被認為是個遺留的類,如果你尋求在疊代的時候修改Map,你應該使用CocurrentHashMap。

9.Java 中的 HashSet,内部是如何工作的?

HashSet 的内部采用 HashMap來實作。由于 Map 需要 key 和 value,是以所有 key 的都有一個預設 value。類似于 HashMap,HashSet 不允許重複的 key,隻允許有一個null key,意思就是 HashSet 中隻允許存儲一個 null 對象。

10.寫一段代碼在周遊 ArrayList 時移除一個元素?

該問題的關鍵在于面試者使用的是 ArrayList 的 remove() 還是 Iterator 的 remove()方法。使用疊代器更加線程安全,因為它可以確定,在目前周遊的集合元素被更改的時候,它會抛出ConcurrentModificationException。

11.ArrayList 和 HashMap 的預設大小是多數?

在 Java 7 中,ArrayList 的預設大小是 10 個元素,HashMap 的預設大小是16個元素(必須是2的幂)。這就是 Java 7 中 ArrayList 和 HashMap 類的代碼片段:

// from ArrayList.java JDK 1.7
private static final int DEFAULT_CAPACITY = 10;
 
//from HashMap.java JDK 7
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
           

12.Java 中,Comparator 與 Comparable 有什麼不同?

Comparable 接口用于定義對象的自然順序,而 comparator 通常用于定義使用者定制的順序。Comparable 總是隻有一個,但是可以有多個 comparator 來定義對象的順序。

13.Java集合架構的基礎接口有哪些?

Collection為集合層級的根接口。一個集合代表一組對象,這些對象即為它的元素。Java平台不提供這個接口任何直接的實作。

Set是一個不能包含重複元素的集合。這個接口對數學集合抽象進行模組化,被用來代表集合,就如一副牌。

List是一個有序集合,可以包含重複元素。你可以通過它的索引來通路任何元素。List更像長度動态變換的數組。

Map是一個将key映射到value的對象.一個Map不能包含重複的key:每個key最多隻能映射一個value。

一些其它的接口有Queue、Dequeue、SortedSet、SortedMap和ListIterator。

14.Iterator是什麼?

Iterator接口提供周遊任何Collection的接口。我們可以從一個Collection中使用疊代器方法來擷取疊代器執行個體。疊代器取代了Java集合架構中的Enumeration。疊代器允許調用者在疊代過程中移除元素。

15.Enumeration和Iterator接口的差別?

Enumeration的速度是Iterator的兩倍,也使用更少的記憶體。Enumeration是非常基礎的,也滿足了基礎的需要。但是,與Enumeration相比,Iterator更加安全,因為當一個集合正在被周遊的時候,它會阻止其它線程去修改集合。

疊代器取代了Java集合架構中的Enumeration。疊代器允許調用者從集合中移除元素,而Enumeration不能做到。為了使它的功能更加清晰,疊代器方法名已經經過改善。

16.Iterater和ListIterator之間有什麼差別?

(1)我們可以使用Iterator來周遊Set和List集合,而ListIterator隻能周遊List。

(2)Iterator隻可以向前周遊,而LIstIterator可以雙向周遊。

(3)ListIterator從Iterator接口繼承,然後添加了一些額外的功能,比如添加一個元素、替換一個元素、擷取前面或後面元素的索引位置。

17.在疊代一個集合的時候,如何避免ConcurrentModificationException?

在周遊一個集合的時候,我們可以使用并發集合類來避免ConcurrentModificationException,比如使用CopyOnWriteArrayList,而不是ArrayList。

18.UnsupportedOperationException是什麼?

UnsupportedOperationException是用于表明操作不支援的異常。在JDK類中已被大量運用,在集合架構java.util.Collections.UnmodifiableCollection将會在所有add和remove操作中抛出這個異常。

19.在Java中,HashMap是如何工作的?

HashMap在Map.Entry靜态内部類實作中存儲key-value對。HashMap使用雜湊演算法,在put和get方法中,它使用hashCode()和equals()方法。當我們通過傳遞key-value對調用put方法的時候,HashMap使用Key hashCode()和雜湊演算法來找出存儲key-value對的索引。Entry存儲在LinkedList中,是以如果存在entry,它使用equals()方法來檢查傳遞的key是否已經存在,如果存在,它會覆寫value,如果不存在,它會建立一個新的entry然後儲存。當我們通過傳遞key調用get方法時,它再次使用hashCode()來找到數組中的索引,然後使用equals()方法找出正确的Entry,然後傳回它的值。

其它關于HashMap比較重要的問題是容量、負荷系數和閥值調整。HashMap預設的初始容量是32,負荷系數是0.75。閥值是為負荷系數乘以容量,無論何時我們嘗試添加一個entry,如果map的大小比閥值大的時候,HashMap會對map的内容進行重新哈希,且使用更大的容量。容量總是2的幂,是以如果你知道你需要存儲大量的key-value對,比如緩存從資料庫裡面拉取的資料,使用正确的容量和負荷系數對HashMap進行初始化是個不錯的做法。

和HashMap一起問的會有ConcurrentHashMap的底層結構,關于這塊他們倆的底層結構,之後會寫一個源碼分析出來。

20.hashCode()和equals()方法有何重要性?

HashMap使用Key對象的hashCode()和equals()方法去決定key-value對的索引。當我們試着從HashMap中擷取值的時候,這些方法也會被用到。如果這些方法沒有被正确地實作,在這種情況下,兩個不同Key也許會産生相同的hashCode()和equals()輸出,HashMap将會認為它們是相同的,然後覆寫它們,而非把它們存儲到不同的地方。同樣的,所有不允許存儲重複資料的集合類都使用hashCode()和equals()去查找重複,是以正确實作它們非常重要。equals()和hashCode()的實作應該遵循以下規則:

(1)如果o1.equals(o2),那麼o1.hashCode() == o2.hashCode()總是為true的。

(2)如果o1.hashCode() == o2.hashCode(),并不意味着o1.equals(o2)會為true。

21.我們能否使用任何類作為Map的key?

我們可以使用任何類作為Map的key,然而在使用它們之前,需要考慮以下幾點:

(1)如果類重寫了equals()方法,它也應該重寫hashCode()方法。

(2)類的所有執行個體需要遵循與equals()和hashCode()相關的規則。請參考之前提到的這些規則。

(3)如果一個類沒有使用equals(),你不應該在hashCode()中使用它。

(4)使用者自定義key類的最佳實踐是使之為不可變的,這樣,hashCode()值可以被緩存起來,擁有更好的性能。不可變的類也可以確定hashCode()和equals()在未來不會改變,這樣就會解決與可變相關的問題了。

// 比如,我有一個類MyKey,在HashMap中使用它。
// 傳遞給MyKey的name參數被用于equals()和hashCode()中
MyKey key = new MyKey('Pankaj'); //assume hashCode=1234
myHashMap.put(key, 'Value');
// 以下的代碼會改變key的hashCode()和equals()值
key.setName('Amit'); //assume new hashCode=7890
// 下面會傳回null,因為HashMap會嘗試查找存儲同樣索引的key,而key已被改變了,比對失敗,傳回null
myHashMap.get(new MyKey('Pankaj'));
// 那就是為何String和Integer被作為HashMap的key大量使用。
           

22.如何決定選用HashMap還是TreeMap?

對于在Map中插入、删除和定位元素這類操作,HashMap是最好的選擇。然而,假如你需要對一個有序的key集合進行周遊,TreeMap是更好的選擇。基于你的collection的大小,也許向HashMap中添加元素會更快,将map換為TreeMap進行有序key的周遊。

23.BlockingQueue是什麼?

Java.util.concurrent.BlockingQueue是一個隊列,在進行檢索或移除一個元素的時候,它會等待隊列變為非空;當在添加一個元素時,它會等待隊列中的可用空間。BlockingQueue接口是Java集合架構的一部分,主要用于實作生産者-消費者模式。我們不需要擔心等待生産者有可用的空間,或消費者有可用的對象,因為它都在BlockingQueue的實作類中被處理了。Java提供了集中BlockingQueue的實作,比如ArrayBlockingQueue、LinkedBlockingQueue、PriorityBlockingQueue,、SynchronousQueue等。

(後續也會對隊列這塊做一個源碼分析)

24.隊列和棧是什麼,列出它們的差別?

棧和隊列兩者都被用來預存儲資料。java.util.Queue是一個接口,它的實作類在Java并發包中。隊列允許先進先出(FIFO)檢索元素,但并非總是這樣。Deque接口允許從兩端檢索元素。

棧與隊列很相似,但它允許對元素進行後進先出(LIFO)進行檢索。

Stack是一個擴充自Vector的類,而Queue是一個接口。

25.我們如何對一組對象進行排序?

如果我們需要對一個對象數組進行排序,我們可以使用Arrays.sort()方法。如果我們需要排序一個對象清單,我們可以使用Collection.sort()方法。兩個類都有用于自然排序(使用Comparable)或基于标準的排序(使用Comparator)的重載方法sort()。

26.當一個集合被作為參數傳遞給一個函數時,如何才可以確定函數不能修改它?

在作為參數傳遞之前,我們可以使用Collections.unmodifiableCollection(Collection c)方法建立一個隻讀集合,這将確定改變集合的任何操作都會抛出UnsupportedOperationException。

37.我們如何從給定集合那裡建立一個synchronized的集合?

27.與Java集合架構相關的有哪些最好的實踐?

(1)根據需要選擇正确的集合類型。比如,如果指定了大小,我們會選用Array而非ArrayList。如果我們想根據插入順序周遊一個Map,我們需要使用TreeMap。如果我們不想重複,我們應該使用Set。

(2)一些集合類允許指定初始容量,是以如果我們能夠估計到存儲元素的數量,我們可以使用它,就避免了重新哈希或大小調整。

(3)基于接口程式設計,而非基于實作程式設計,它允許我們後來輕易地改變實作。

(4)總是使用類型安全的泛型,避免在運作時出現ClassCastException。

(5)使用JDK提供的不可變類作為Map的key,可以避免自己實作hashCode()和equals()。

(6)盡可能使用Collections工具類,或者擷取隻讀、同步或空的集合,而非編寫自己的實作。它将會提供代碼重用性,它有着更好的穩定性和可維護性。

Spring架構

1.使用Spring架構的好處是什麼?

  • 輕量:Spring 是輕量的,基本的版本大約2MB。
  • 控制反轉:Spring通過控制反轉實作了松散耦合,對象們給出它們的依賴,而不是建立或查找依賴的對象們。
  • 面向切面的程式設計(AOP):Spring支援面向切面的程式設計,并且把應用業務邏輯和系統服務分開。
  • 容器:Spring 包含并管理應用中對象的生命周期和配置。
  • MVC架構:Spring的WEB架構是個精心設計的架構,是Web架構的一個很好的替代品。
  • 事務管理:Spring 提供一個持續的事務管理接口,可以擴充到上至本地事務下至全局事務(JTA)。
  • 異常處理:Spring 提供友善的API把具體技術相關的異常(比如由JDBC,Hibernate or JDO抛出的)轉化為一緻的unchecked 異常。
  1. 什麼是Spring IOC 容器?

Spring IOC 負責建立對象,管理對象(通過依賴注入(DI),裝配對象,配置對象,并且管理這些對象的整個生命周期。

3.IOC的優點是什麼?

IOC 或 依賴注入把應用的代碼量降到最低。它使應用容易測試,單元測試不再需要單例和JNDI查找機制。最小的代價和最小的侵入性使松散耦合得以實作。IOC容器支援加載服務時的餓漢式初始化和懶加載。

4.ApplicationContext通常的實作是什麼?

  • FileSystemXmlApplicationContext :此容器從一個XML檔案中加載beans的定義,XML Bean 配置檔案的全路徑名必須提供給它的構造函數。
  • ClassPathXmlApplicationContext:此容器也從一個XML檔案中加載beans的定義,這裡,你需要正确設定classpath因為這個容器将在classpath裡找bean配置。
  • WebXmlApplicationContext:此容器加載一個XML檔案,此檔案定義了一個WEB應用的所有bean。
  1. 有哪些不同類型的IOC(依賴注入)方式?
  • 構造器依賴注入:構造器依賴注入通過容器觸發一個類的構造器來實作的,該類有一系列參數,每個參數代表一個對其他類的依賴。
  • Setter方法注入:Setter方法注入是容器通過調用無參構造器或無參static工廠 方法執行個體化bean之後,調用該bean的setter方法,即實作了基于setter的依賴注入。

6.解釋Spring支援的幾種bean的作用域?

  • singleton : bean在每個Spring ioc 容器中隻有一個執行個體。(預設預設)
  • prototype:一個bean的定義可以有多個執行個體。
  • request:每次http請求都會建立一個bean,該作用域僅在基于web的Spring ApplicationContext情形下有效。
  • session:在一個HTTP Session中,一個bean定義對應一個執行個體。該作用域僅在基于web的Spring ApplicationContext情形下有效。
  • global-session:在一個全局的HTTP Session中,一個bean定義對應一個執行個體。該作用域僅在基于web的Spring ApplicationContext情形下有效。

7.Spring架構中的單例bean是線程安全的嗎?

不,Spring架構中的單例bean不是線程安全的。

8.解釋Spring架構中bean的生命周期?

  • Spring容器 從XML 檔案中讀取bean的定義,并執行個體化bean。
  • Spring根據bean的定義填充所有的屬性。
  • 如果bean實作了BeanNameAware 接口,Spring 傳遞bean 的ID 到 setBeanName方法。
  • 如果Bean 實作了 BeanFactoryAware 接口, Spring傳遞beanfactory 給setBeanFactory 方法。
  • 如果有任何與bean相關聯的BeanPostProcessors,Spring會在postProcesserBeforeInitialization()方法内調用它們。
  • 如果bean實作IntializingBean了,調用它的afterPropertySet方法,如果bean聲明了初始化方法,調用此初始化方法。
  • 如果有BeanPostProcessors 和bean 關聯,這些bean的postProcessAfterInitialization() 方法将被調用。
  • 如果bean實作了 DisposableBean,它将調用destroy()方法。

9.哪些是重要的bean生命周期方法? 你能重載它們嗎?

有兩個重要的bean 生命周期方法,第一個是setup , 它是在容器加載bean的時候被調用。第二個方法是 teardown 它是在容器解除安裝類的時候被調用。

The bean 标簽有兩個重要的屬性(init-method和destroy-method)。用它們你可以自己定制初始化和登出方法。它們也有相應的注解(@PostConstruct和@PreDestroy)。

10.解釋不同方式的自動裝配 ?

有五種自動裝配的方式,可以用來指導Spring容器用自動裝配方式來進行依賴注入。

  • no:預設的方式是不進行自動裝配,通過顯式設定ref 屬性來進行裝配。
  • byName:通過參數名 自動裝配,Spring容器在配置檔案中發現bean的autowire屬性被設定成byname,之後容器試圖比對、裝配和該bean的屬性具有相同名字的bean。
  • byType::通過參數類型自動裝配,Spring容器在配置檔案中發現bean的autowire屬性被設定成byType,之後容器試圖比對、裝配和該bean的屬性具有相同類型的bean。如果有多個bean符合條件,則抛出錯誤。
  • constructor:這個方式類似于byType, 但是要提供給構造器參數,如果沒有确定的帶參數的構造器參數類型,将會抛出異常。
  • autodetect:首先嘗試使用constructor來自動裝配,如果無法工作,則使用byType方式。

11.各個注解的含義?

  • @Required:這個注解表明bean的屬性必須在配置的時候設定,通過一個bean定義的顯式的屬性值或通過自動裝配,若@Required注解的bean屬性未被設定,容器将抛出BeanInitializationException。
  • @Autowired:注解提供了更細粒度的控制,包括在何處以及如何完成自動裝配。它的用法和@Required一樣,修飾setter方法、構造器、屬性或者具有任意名稱多個參數的PN方法。
  • @Qualifier:當有多個相同類型的bean卻隻有一個需要自動裝配時,将@Qualifier 注解和@Autowire 注解結合使用以消除這種混淆,指定需要裝配的确切的bean。

12.Spring支援的事務管理類型?

  • 程式設計式事務管理:這意味你通過程式設計的方式管理事務,給你帶來極大的靈活性,但是難維護。
  • 聲明式事務管理:這意味着你可以将業務代碼和事務管理分離,你隻需用注解和XML配置來管理事務。

13.有幾種不同類型的自動代理?

  • BeanNameAutoProxyCreator
  • DefaultAdvisorAutoProxyCreator
  • Metadata autoproxying

14.Aspect 切面

AOP核心就是切面,它将多個類的通用行為封裝成可重用的子產品,該子產品含有一組API提供橫切功能。比如,一個日志子產品可以被稱作日志的AOP切面。根據需求的不同,一個應用程式可以有若幹切面。在Spring AOP中,切面通過帶有@Aspect注解的類實作。

15.在Spring AOP 中,關注點和橫切關注的差別是什麼?

  • 關注點是應用中一個子產品的行為,一個關注點可能會被定義成一個我們想實作的一個功能。
  • 橫切關注點是一個關注點,此關注點是整個應用都會使用的功能,并影響整個應用,比如日志,安全和資料傳輸,幾乎應用的每個子產品都需要的功能。是以這些都屬于橫切關注點。

16.通知

通知是個在方法執行前或執行後要做的動作,實際上是程式執行時要通過SpringAOP架構觸發的代碼段。

Spring切面可以應用五種類型的通知:

  • before:前置通知,在一個方法執行前被調用。
  • after: 在方法執行之後調用的通知,無論方法執行是否成功。
  • after-returning: 僅當方法成功完成後執行的通知。
  • after-throwing: 在方法抛出異常退出時執行的通知。
  • around: 在方法執行之前和之後調用的通知。