2020JAVA面試題附答案(持續更新版)
前言:勤奮才是改變你命運的唯一捷徑。
整理不易,各位看官點贊再看更舒適,養成好習慣(●´∀`●)
JAVA基礎
1.JAVA中的幾種基本類型,各占用多少字節?
下圖單位是bit,非字節 1B=8bit
2.String能被繼承嗎?為什么?
不可以,因為String類有final修飾符,而final修飾的類是不能被繼承的,實現細節不允許改變。平常我們定義的String str=”a”;其實和String str=new String(“a”)還是有差異的。
前者默認調用的是String.valueOf來返回String實例對象,至於調用哪個則取決於你的賦值,比如String num=1,調用的是
public static String valueOf(int i) { return Integer.toString(i); }
- 1
- 2
- 3
后者則是調用如下部分:
public String(String original) { this.value = original.value; this.hash = original.hash; }
- 1
- 2
- 3
- 4
最后我們的變量都存儲在一個char數組中
private final char value[];
- 1
3.String, Stringbuffer, StringBuilder 的區別。
String 字符串常量(final修飾,不可被繼承),String是常量,當創建之后即不能更改。(可以通過StringBuffer和StringBuilder創建String對象(常用的兩個字符串操作類)。)
==StringBuffer 字符串變量(線程安全),==其也是final類別的,不允許被繼承,其中的絕大多數方法都進行了同步處理,包括常用的Append方法也做了同步處理(synchronized修飾)。其自jdk1.0起就已經出現。其toString方法會進行對象緩存,以減少元素復制開銷。
public synchronized String toString() { if (toStringCache == null) { toStringCache = Arrays.copyOfRange(value, 0, count); } return new String(toStringCache, true); }
- 1
- 2
- 3
- 4
- 5
- 6
==StringBuilder 字符串變量(非線程安全)==其自jdk1.5起開始出現。與StringBuffer一樣都繼承和實現了同樣的接口和類,方法除了沒使用synch修飾以外基本一致,不同之處在於最后toString的時候,會直接返回一個新對象。
public String toString() { // Create a copy, don’t share the array return new String(value, 0, count); }
- 1
- 2
- 3
- 4
4.ArrayList 和 LinkedList 有什么區別。
ArrayList和LinkedList都實現了List接口,有以下的不同點:
1、ArrayList是基於索引的數據接口,它的底層是數組。它可以以O(1)時間復雜度對元素進行隨機訪問。與此對應,LinkedList是以元素列表的形式存儲它的數據,每一個元素都和它的前一個和后一個元素鏈接在一起,在這種情況下,查找某個元素的時間復雜度是O(n)。
2、相對於ArrayList,LinkedList的插入,添加,刪除操作速度更快,因為當元素被添加到集合任意位置的時候,不需要像數組那樣重新計算大小或者是更新索引。
3、LinkedList比ArrayList更占內存,因為LinkedList為每一個節點存儲了兩個引用,一個指向前一個元素,一個指向下一個元素。
5.講講類的實例化順序,比如父類靜態數據,構造函數,字段,子類靜態數據,構造函數,字段,當 new 的時候, 他們的執行順序。
此題考察的是類加載器實例化時進行的操作步驟(加載–>連接->初始化)。
父類靜態代變量、
父類靜態代碼塊、
子類靜態變量、
子類靜態代碼塊、
父類非靜態變量(父類實例成員變量)、
父類構造函數、
子類非靜態變量(子類實例成員變量)、
子類構造函數。
測試demo
參閱博客《深入理解類加載》
6.用過哪些 Map 類,都有什么區別,HashMap 是線程安全的嗎,並發下使用的 Map 是什么,他們內部原理分別是什么,比如存儲方式, hashcode,擴容, 默認容量等。
hashMap是線程不安全的,HashMap是數組+鏈表+紅黑樹(JDK1.8增加了紅黑樹部分)實現的,采用哈希表來存儲的,
參考鏈接
JAVA8 的 ConcurrentHashMap 為什么放棄了分段鎖,有什么問題嗎,如果你來設計,你如何設計。
參考鏈接
7.有沒有有順序的 Map 實現類, 如果有, 他們是怎么保證有序的。
TreeMap和LinkedHashMap是有序的(TreeMap默認升序,LinkedHashMap則記錄了插入順序)。
參考鏈接
8.抽象類和接口的區別,類可以繼承多個類么,接口可以繼承多個接口么,類可以實現多個接口么。
1、抽象類和接口都不能直接實例化,如果要實例化,抽象類變量必須指向實現所有抽象方法的子類對象,接口變量必須指向實現所有接口方法的類對象。
2、抽象類要被子類繼承,接口要被類實現。
3、接口只能做方法申明,抽象類中可以做方法申明,也可以做方法實現
4、接口里定義的變量只能是公共的靜態的常量,抽象類中的變量是普通變量。
5、抽象類里的抽象方法必須全部被子類所實現,如果子類不能全部實現父類抽象方法,那么該子類只能是抽象類。同樣,一個實現接口的時候,如不能全部實現接口方法,那么該類也只能為抽象類。
6、抽象方法只能申明,不能實現。abstract void abc();不能寫成abstract void abc(){}。
7、抽象類里可以沒有抽象方法
8、如果一個類里有抽象方法,那么這個類只能是抽象類
9、抽象方法要被實現,所以不能是靜態的,也不能是私有的。
10、接口可繼承接口,並可多繼承接口,但類只能單根繼承。
9.繼承和聚合的區別在哪。
繼承指的是一個類(稱為子類、子接口)繼承另外的一個類(稱為父類、父接口)的功能,並可以增加它自己的新功能的能力,繼承是類與類或者接口與接口之間最常見的關系;在Java中此類關系通過關鍵字extends明確標識,在設計時一般沒有爭議性;
聚合是關聯關系的一種特例,他體現的是整體與部分、擁有的關系,即has-a的關系,此時整體與部分之間是可分離的,他們可以具有各自的生命周期,部分可以屬於多個整體對象,也可以為多個整體對象共享;比如計算機與CPU、公司與員工的關系等;表現在代碼層面,和關聯關系是一致的,只能從語義級別來區分;
參考鏈接
10.講講你理解的 nio和 bio 的區別是啥,談談 reactor 模型。
IO(BIO)是面向流的,NIO是面向緩沖區的
BIO:Block IO 同步阻塞式 IO,就是我們平常使用的傳統 IO,它的特點是模式簡單使用方便,並發處理能力低。
NIO:New IO 同步非阻塞 IO,是傳統 IO 的升級,客戶端和服務器端通過 Channel(通道)通訊,實現了多路復用。
AIO:Asynchronous IO 是 NIO 的升級,也叫 NIO2,實現了異步非堵塞 IO ,異步 IO 的操作基於事件和回調機制。
參考鏈接1
參考鏈接2
11.反射的原理,反射創建類實例的三種方式是什么
參考鏈接1
參考鏈接2
12.反射中,Class.forName 和 ClassLoader 區別。
參考鏈接
13.描述動態代理的幾種實現方式,分別說出相應的優缺點。
Jdk cglib jdk底層是利用反射機制,需要基於接口方式,這是由於
Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
- 1
- 2
Cglib則是基於asm框架,實現了無反射機制進行代理,利用空間來換取了時間,代理效率高於jdk
參考鏈接
動態代理與 cglib 實現的區別
同上(基於invocationHandler和methodInterceptor)
14.為什么 CGlib 方式可以對接口實現代理。
同上
15.final 的用途
類、變量、方法
final 修飾的類叫最終類,該類不能被繼承。
final 修飾的方法不能被重寫。
final 修飾的變量叫常量,常量必須初始化,初始化之后值就不能被修改。
參考鏈接
16.寫出三種單例模式實現。
懶漢式單例,餓漢式單例,雙重檢查等
參考鏈接
17.如何在父類中為子類自動完成所有的 hashcode 和 equals 實現?這么做有何優劣。
同時復寫hashcode和equals方法,優勢可以添加自定義邏輯,且不必調用超類的實現。
參考鏈接
18.請結合 OO 設計理念,談談訪問修飾符 public、private、protected、default 在應用設計中的作用。
訪問修飾符,主要標示修飾塊的作用域,方便隔離防護
類中的數據成員和成員函數據具有的訪問權限包括:public、private、protect、default(包訪問權限) 作用域 當前類 同一package 子孫類 其他package public √ √ √ √ protected √ √ √ × default √ √ × × private √ × × × public 所有類可見 protected 本包和所有子類都可見(本包中的子類非子類均可訪問,不同包中的子類可以訪問,不是子類不能訪問) default 本包可見(即默認的形式)(本包中的子類非子類均可訪問,不同包中的類及子類均不能訪問) priavte 本類可見
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
public: Java語言中訪問限制最寬的修飾符,一般稱之為“公共的”。被其修飾的類、屬性以及方法不僅可以跨類訪問,而且允許跨包(package)訪問。
private: Java語言中對訪問權限限制的最窄的修飾符,一般稱之為“私有的”。被其修飾的類、屬性以及方法只能被該類的對象訪問,其子類不能訪問,更不能允許跨包訪問。
protect: 介於public 和 private 之間的一種訪問修飾符,一般稱之為“保護形”。被其修飾的類、屬性以及方法只能被類本身的方法及子類訪問,即使子類在不同的包中也可以訪問。
default:即不加任何訪問修飾符,通常稱為"默認訪問模式"。該模式下,只允許在同一個包中進行訪問。
19.深拷貝和淺拷貝區別。
參考鏈接
20.數組和鏈表數據結構描述,各自的時間復雜度
參考鏈接
21.error 和 exception 的區別,CheckedException,RuntimeException 的區別
參考鏈接
22.請列出 5 個運行時異常。
同上
23.在自己的代碼中,如果創建一個 java.lang.String 對象,這個對象是否可以被類加載器加載?為什么
類加載無須等到“首次使用該類”時加載,jvm允許預加載某些類。。。。
參考鏈接
24.說一說你對 java.lang.Object 對象中 hashCode 和 equals 方法的理解。在什么場景下需要重新實現這兩個方法。
參考上邊試題(17)
25.在 jdk1.5 中,引入了泛型,泛型的存在是用來解決什么問題。
泛型的本質是參數化類型,也就是說所操作的數據類型被指定為一個參數,泛型的好處是在編譯的時候檢查類型安全,並且所有的強制轉換都是自動和隱式的,以提高代碼的重用率
參考鏈接
26.這樣的 a.hashcode() 有什么用,與 a.equals(b)有什么關系。
hashcode
hashcode()方法提供了對象的hashCode值,是一個native方法,返回的默認值與System.identityHashCode(obj)一致。
通常這個值是對象頭部的一部分二進制位組成的數字,具有一定的標識對象的意義存在,但絕不定於地址。
作用是:用一個數字來標識對象。比如在HashMap、HashSet等類似的集合類中,如果用某個對象本身作為Key,即要基於這個對象實現Hash的寫入和查找,那么對象本身如何實現這個呢?就是基於hashcode這樣一個數字來完成的,只有數字才能完成計算和對比操作。
hashcode是否唯一
hashcode只能說是標識對象,在hash算法中可以將對象相對離散開,這樣就可以在查找數據的時候根據這個key快速縮小數據的范圍,但hashcode不一定是唯一的,所以hash算法中定位到具體的鏈表后,需要循環鏈表,然后通過equals方法來對比Key是否是一樣的。
equals與hashcode的關系
equals相等兩個對象,則hashcode一定要相等。但是hashcode相等的兩個對象不一定equals相等。
參考鏈接
27.有沒有可能 2 個不相等的對象有相同的 hashcode。
有
實例:
String str1 = "通話"; String str2 = "重地"; System.out.println(String.format("str1:%d | str2:%d", str1.hashCode(),str2.hashCode())); System.out.println(str1.equals(str2)); 執行結果:str1:1179395 | str2:1179395 false
- 1
- 2
- 3
- 4
- 5
- 6
- 7
28.Java 中的 HashSet 內部是如何工作的。
底層是基於hashmap實現的
參考鏈接
什么是序列化,怎么序列化,為什么序列化,反序列化會遇到什么問題,如何解決。
參考鏈接
29. JDK 和 JRE 有什么區別?
JDK:Java Development Kit 的簡稱,java 開發工具包,提供了 java 的開發環境和運行環境。
JRE:Java Runtime Environment 的簡稱,java 運行環境,為 java 的運行提供了所需環境。
具體來說 JDK 其實包含了 JRE,同時還包含了編譯 java 源碼的編譯器 javac,還包含了很多 java 程序調試和分析的工具。簡單來說:如果你需要運行 java 程序,只需安裝 JRE 就可以了,如果你需要編寫 java 程序,需要安裝 JDK。
30. == 和 equals 的區別是什么?
== 解讀:
對於基本類型和引用類型 == 的作用效果是不同的,如下所示:
基本類型:比較的是值是否相同;
引用類型:比較的是引用是否相同;
實例:
String x = "string"; String y = "string"; String z = new String("string"); System.out.println(x==y); // true,引用相同 System.out.println(x==z); // false,==:string比較引用,開辟了新的堆內存空間,所以false System.out.println(x.equals(y)); // true,equals:string:比較值,相同 System.out.println(x.equals(z)); // true,equals:string比較值,相同
- 1
- 2
- 3
- 4
- 5
- 6
- 7
equals 解讀:
equals 本質上就是 ==,只不過 String 和 Integer 等重寫了 equals 方法,把它變成了值比較。看下面的代碼就明白了。
首先來看默認情況下 equals 比較一個(有相同值的對象),代碼如下:
public class Cat { private String name; public Cat(String name){ this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } public static void main(String[] args) { Cat c1 = new Cat("cat1");//c1是Cat的實例化對象,c2同理 Cat c2 = new Cat("cat2"); String s1 = new String("隔壁老王"); String s2 = new String("隔壁老王"); System.out.println(c1.equals(c2));//false,equals在比較的類對象的時候比較的是引用 System.out.println(s1.equals(s2)); //true,而在比較string的時候,因為重寫了equals方法,和基本數據類型一樣,比較的是值,所以為true }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
總結 :== 對於基本類型來說是值比較(不難理解,八種基本數據類型是可以有確定值的),對於引用類型來說是比較的是引用(數組、類、接口沒有確定值);而 equals 默認情況下是引用比較,只是很多類重新了 equals 方法,比如 String、Integer 等把它變成了值比較,所以一般情況下 equals 比較的是值是否相等。
31.java 中的 Math.round(-1.5) 等於多少?
等於 -1,因為在數軸上取值時,中間值(0.5)向右取整,所以正 0.5 是往上取整,負 0.5 是直接舍棄。同理,Math.round(1.5) = 2
32.寫一個字符串反轉函數。
// StringBuffer reverse StringBuffer stringBuffer = new StringBuffer(); stringBuffer.append("abcdefg"); System.out.println(stringBuffer.reverse()); // gfedcba // StringBuilder reverse StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append("abcdefg"); System.out.println(stringBuilder.reverse()); // gfedcba
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
33.String 類的常用方法都有那些?
indexOf():返回指定字符的索引。
charAt():返回指定索引處的字符。
replace():字符串替換。
trim():去除字符串兩端空白。
split():分割字符串,返回一個分割后的字符串數組。
getBytes():返回字符串的 byte 類型數組。
length():返回字符串長度。
toLowerCase():將字符串轉成小寫字母。
toUpperCase():將字符串轉成大寫字符。
substring():截取字符串。
equals():字符串比較。
34.抽象類必須要有抽象方法嗎?
不需要,抽象類不一定非要有抽象方法。
示例代碼:
public abstract class noAbstractMethod{ public static void main(String[] args) { sayHi(); } public static void sayHi() { System.out.println("hi~"); } } 結果:hi~
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
35.java 中 IO 流分為幾種?
按功能來分:輸入流(input)、輸出流(output)。
按類型來分:字節流和字符流。
字節流和字符流的區別是:字節流按 8 位傳輸以字節為單位輸入輸出數據,字符流按 16 位傳輸以字符為單位輸入輸出數據。
36.Files的常用方法都有哪些?
Files.exists():檢測文件路徑是否存在。
Files.createFile():創建文件。
Files.createDirectory():創建文件夾。
Files.delete():刪除一個文件或目錄。
Files.copy():復制文件。
Files.move():移動文件。
Files.size():查看文件個數。
Files.read():讀取文件。
Files.write():寫入文件。
37.List、Set、Map 之間的區別是什么?
38.如何實現數組和 List 之間的轉換?
List轉換成為數組:調用ArrayList的toArray方法。
數組轉換成為List:調用Arrays的asList方法。
39. ArrayList 和 Vector 的區別是什么?
Vector是同步的,而ArrayList不是。然而,如果你尋求在迭代的時候對列表進行改變,你應該使用CopyOnWriteArrayList。
ArrayList比Vector快,它是異步,不會過載。
ArrayList更加通用,因為我們可以使用Collections工具類輕易地獲取同步列表和只讀列表。
40.Array 和 ArrayList 有何區別?
Array可以容納基本類型和對象,而ArrayList只能容納對象。
Array是指定大小的,而ArrayList大小是固定的。
Array沒有提供ArrayList那么多功能,比如addAll、removeAll和iterator等。
41.在 Queue 中 poll()和 remove()有什么區別?
poll() 和 remove() 都是從隊列中取出一個元素,但是 poll() 在獲取元素失敗的時候會返回空,但是 remove() 失敗的時候會拋出異常。
42. 哪些集合類是線程安全的?
vector:就比arraylist多了個同步化機制(線程安全),因為效率較低,現在已經不太建議使用。在web應用中,特別是前台頁面,往往效率(頁面響應速度)是優先考慮的。
statck:堆棧類,先進后出。
hashtable:就比hashmap多了個線程安全。
enumeration:枚舉,相當於迭代器。
43.迭代器 Iterator 是什么?
迭代器是一種設計模式,它是一個對象,它可以遍歷並選擇序列中的對象,而開發人員不需要了解該序列的底層結構。迭代器通常被稱為“輕量級”對象,因為創建它的代價小。
44.Iterator 怎么使用?有什么特點?
Java中的Iterator功能比較簡單,並且只能單向移動:
(1) 使用方法iterator()要求容器返回一個Iterator。第一次調用Iterator的next()方法時,它返回序列的第一個元素。注意:iterator()方法是java.lang.Iterable接口,公共基類Collection提供iterator()方法。
(2) 使用next()獲得序列中的下一個元素。
(3) 使用hasNext()檢查序列中是否還有元素。
(4) 使用remove()將迭代器新返回的元素刪除。
Iterator是Java迭代器最簡單的實現,為List設計的ListIterator具有更多的功能,它可以從兩個方向遍歷List,也可以從List中插入和刪除元素。
45. Iterator 和 ListIterator 有什么區別?
Iterator可用來遍歷Set和List集合,但是ListIterator只能用來遍歷List,見名知意,Set並不能使用ListIterator
Iterator對集合只能是前向遍歷,ListIterator既可以前向也可以后向。
ListIterator實現了Iterator接口,並包含其他的功能,比如:增加元素,替換元素,獲取前一個和后一個元素的索引,等等。
46.synchronized 和 volatile 的區別是什么?
volatile本質是在告訴jvm當前變量在寄存器(工作內存)中的值是不確定的,需要從主存中讀取; synchronized則是鎖定當前變量,只有當前線程可以訪問該變量,其他線程被阻塞住。
volatile僅能使用在變量級別;synchronized則可以使用在變量、方法、和類級別的。
volatile僅能實現變量的修改可見性,不能保證原子性;而synchronized則可以保證變量的修改可見性和原子性。
volatile不會造成線程的阻塞;synchronized可能會造成線程的阻塞。
volatile標記的變量不會被編譯器優化;synchronized標記的變量可以被編譯器優化。
JVM 知識
1.什么情況下會發生棧內存溢出。
如果線程請求的棧深度大於虛擬機所允許的深度,將拋出StackOverflowError異常。 如果虛擬機在動態擴展棧時無法申請到足夠的內存空間,則拋出OutOfMemoryError異常。
參考鏈接
2.JVM 的內存結構,Eden 和 Survivor 比例。
eden 和 survior 是按8比1分配的
參考鏈接
3.jvm 中一次完整的 GC 流程是怎樣的,對象如何晉升到老年代,說說你知道的幾種主要的jvm 參數。
對象誕生即新生代->eden,在進行minor gc過程中,如果依舊存活,移動到from,變成Survivor,進行標記代數,如此檢查一定次數后,晉升為老年代,
參考鏈接1
參考鏈接2
參考鏈接3
4.你知道哪幾種垃圾收集器,各自的優缺點,重點講下 cms,包括原理,流程,優缺點
Serial、parNew、ParallelScavenge、SerialOld、ParallelOld、CMS、G1
參考鏈接
5.垃圾回收算法的實現原理。
參考鏈接
6.當出現了內存溢出,你怎么排錯。
首先分析是什么類型的內存溢出,對應的調整參數或者優化代碼。
參考鏈接
7.JVM 內存模型的相關知識了解多少,比如重排序,內存屏障,happen-before,主內存,工作內存等。
內存屏障:為了保障執行順序和可見性的一條cpu指令
重排序:為了提高性能,編譯器和處理器會對執行進行重拍
happen-before:操作間執行的順序關系。有些操作先發生。
主內存:共享變量存儲的區域即是主內存
工作內存:每個線程copy的本地內存,存儲了該線程以讀/寫共享變量的副本
參考鏈接1
參考鏈接2
參考鏈接3
8.簡單說說你了解的類加載器。
類加載器的分類(bootstrap,ext,app,curstom),類加載的流程(load-link-init)
參考鏈接
9.講講 JAVA 的反射機制。
Java程序在運行狀態可以動態的獲取類的所有屬性和方法,並實例化該類,調用方法的功能
參考鏈接
10.你們線上應用的 JVM 參數有哪些。
-server
-Xms6000M
-Xmx6000M
-Xmn500M
-XX:PermSize=500M
-XX:MaxPermSize=500M
-XX:SurvivorRatio=65536
-XX:MaxTenuringThreshold=0
-Xnoclassgc
-XX:+DisableExplicitGC
-XX:+UseParNewGC
-XX:+UseConcMarkSweepGC
-XX:+UseCMSCompactAtFullCollection
-XX:CMSFullGCsBeforeCompaction=0
-XX:+CMSClassUnloadingEnabled
-XX:-CMSParallelRemarkEnabled
-XX:CMSInitiatingOccupancyFraction=90
-XX:SoftRefLRUPolicyMSPerMB=0
-XX:+PrintClassHistogram
-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps
-XX:+PrintHeapAtGC
-Xloggc:log/gc.log
11.g1 和 cms 區別,吞吐量優先和響應優先的垃圾收集器選擇。
Cms是以獲取最短回收停頓時間為目標的收集器。基於標記-清除算法實現。比較占用cpu資源,切易造成碎片。
G1是面向服務端的垃圾收集器,是jdk9默認的收集器,基於標記-整理算法實現。可利用多核、多cpu,保留分代,實現可預測停頓,可控。
參考鏈接
請解釋如下 jvm 參數的含義:
-server -Xms512m -Xmx512m -Xss1024K
-XX:PermSize=256m -XX:MaxPermSize=512m -XX:MaxTenuringThreshold=20
XX:CMSInitiatingOccupancyFraction=80 -XX:+UseCMSInitiatingOccupancyOnly。
Server模式啟動
最小堆內存512m
最大512m
每個線程棧空間1m
永久代256m
最大永久代512m
最大轉為老年代檢查次數20
Cms回收開啟時機:內存占用80%
命令JVM不基於運行時收集的數據來啟動CMS垃圾收集周期
開源框架知識
1.簡單講講 tomcat 結構,以及其類加載器流程。
Server- --多個service
Container級別的:–>engine–》host–>context
Listenter
Connector
Logging、Naming、Session、JMX等等
通過WebappClassLoader 加載class
參考鏈接1
參考鏈接2
參考鏈接3
參考鏈接4
2.tomcat 如何調優,涉及哪些參數。
硬件上選擇,操作系統選擇,版本選擇,jdk選擇,配置jvm參數,配置connector的線程數量,開啟gzip壓縮,trimSpaces,集群等
參考鏈接
3.講講 Spring 加載流程。
通過listener入口,核心是在AbstractApplicationContext的refresh方法,在此處進行裝載bean工廠,bean,創建bean實例,攔截器,后置處理器等。
參考鏈接
4.講講 Spring 事務的傳播屬性。
七種傳播屬性。
事務傳播行為
所謂事務的傳播行為是指,如果在開始當前事務之前,一個事務上下文已經存在,此時有若干選項可以指定一個事務性方法的執行行為。在TransactionDefinition定義中包括了如下幾個表示傳播行為的常量:
①TransactionDefinition.PROPAGATION_REQUIRED:如果當前存在事務,則加入該事務;如果當前沒有事務,則創建一個新的事務。
②TransactionDefinition.PROPAGATION_REQUIRES_NEW:創建一個新的事務,如果當前存在事務,則把當前事務掛起。
③TransactionDefinition.PROPAGATION_SUPPORTS:如果當前存在事務,則加入該事務;如果當前沒有事務,則以非事務的方式繼續運行。
④TransactionDefinition.PROPAGATION_NOT_SUPPORTED:以非事務方式運行,如果當前存在事務,則把當前事務掛起。
⑤TransactionDefinition.PROPAGATION_NEVER:以非事務方式運行,如果當前存在事務,則拋出異常。
⑥TransactionDefinition.PROPAGATION_MANDATORY:如果當前存在事務,則加入該事務;如果當前沒有事務,則拋出異常。
⑦TransactionDefinition.PROPAGATION_NESTED:如果當前存在事務,則創建一個事務作為當前事務的嵌套事務來運行;如果當前沒有事務,則該取值等價於TransactionDefinition.PROPAGATION_REQUIRED。
參考鏈接
5.Spring 如何管理事務的。
編程式和聲明式
同上
6.Spring 怎么配置事務(具體說出一些關鍵的 xml 元素)。
配置事務的方法有兩種:
1)、基於XML的事務配置。
<?xml version="1.0" encoding="UTF-8"?> <!-- from the file 'context.xml' --> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"> <!-- 數據元信息 --> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/> <property name="url" value="jdbc:oracle:thin:@rj-t42:1521:elvis"/> <property name="username" value="root"/> <property name="password" value="root"/> </bean> <!-- 管理事務的類,指定我們用誰來管理我們的事務--> <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <!-- 首先我們要把服務對象聲明成一個bean 例如HelloService --> <bean id="helloService" class="com.yintong.service.HelloService"/> <!-- 然后是聲明一個事物建議tx:advice,spring為我們提供了事物的封裝,這個就是封裝在了<tx:advice/>中 --> <!-- <tx:advice/>有一個transaction-manager屬性,我們可以用它來指定我們的事物由誰來管理。 默認:事務傳播設置是 REQUIRED,隔離級別是DEFAULT --> <tx:advice id="txAdvice" transaction-manager="txManager"> <!-- 配置這個事務建議的屬性 --> <tx:attributes> <!-- 指定所有get開頭的方法執行在只讀事務上下文中 --> <tx:method name="get*" read-only="true"/> <!-- 其余方法執行在默認的讀寫上下文中 --> <tx:method name="*"/> </tx:attributes> </tx:advice> <!-- 我們定義一個切面,它匹配FooService接口定義的所有操作 --