千鋒扣丁學堂Java培訓之企業面試中常見面試題解析

今天千鋒扣丁學堂Java培訓老師給你們分享一篇關於企業面試中常見面試題解析,本文分爲十九個模塊,分別是:Java基礎、容器、多線程、反射、對象拷貝、JavaWeb、異常、網絡、設計模式、Spring/SpringMVC、SpringBoot/SpringCloud、Hibernate、MyBatis、RabbitMQ、Kafka、Zookeeper、MySQL、Redis、JVM,以下圖所示:css

Java基礎html

1.JDK和JRE有什麼區別?面試

JDK:JavaDevelopmentKit的簡稱,Java開發工具包,提供了Java的開發環境和運行環境。ajax

JRE:JavaRuntimeEnvironment的簡稱,Java運行環境,爲Java的運行提供了所需環境。正則表達式

具體來講JDK其實包含了JRE,同時還包含了編譯Java源碼的編譯器Javac,還包含了不少Java程序調試和分析的工具。簡單來講:若是你須要運行Java程序,只需安裝JRE就能夠了,若是你須要編寫Java程序,須要安裝JDK。算法

2.==和equals的區別是什麼?spring

==解讀數據庫

對於基本類型和引用類型==的做用效果是不一樣的,以下所示:編程

基本類型:比較的是值是否相同;json

引用類型:比較的是引用是否相同;

代碼示例:

Stringx="string";

Stringy="string";

Stringz=newString("string");

System.out.println(x==y);//true

System.out.println(x==z);//false

System.out.println(x.equals(y));//true

System.out.println(x.equals(z));//true

代碼解讀:由於x和y指向的是同一個引用,因此==也是true,而newString()方法則重寫開闢了內存空間,因此==結果爲false,而equals比較的一直是值,因此結果都爲true。

equals解讀

equals本質上就是==,只不過String和Integer等重寫了equals方法,把它變成了值比較。看下面的代碼就明白了。

首先來看默認狀況下equals比較一個有相同值的對象,代碼以下:

classCat{

publicCat(Stringname){

this.name=name;

}

privateStringname;

publicStringgetName(){

returnname;

}

publicvoidsetName(Stringname){

this.name=name;

}

}

Catc1=newCat("王磊");

Catc2=newCat("王磊");

System.out.println(c1.equals(c2));//false

輸出結果出乎咱們的意料,居然是false?這是怎麼回事,看了equals源碼就知道了,源碼以下:

publicbooleanequals(Objectobj){

return(this==obj);

}

原來equals本質上就是==。

那問題來了,兩個相同值的String對象,爲何返回的是true?代碼以下:

Strings1=newString("老王");

Strings2=newString("老王");

System.out.println(s1.equals(s2));//true

一樣的,當咱們進入String的equals方法,找到了答案,代碼以下:

publicbooleanequals(ObjectanObject){

if(this==anObject){

returntrue;

}

if(anObjectinstanceofString){

StringanotherString=(String)anObject;

intn=value.length;

if(n==anotherString.value.length){

charv1[]=value;

charv2[]=anotherString.value;

inti=0;

while(n--!=0){

if(v1[i]!=v2[i])

returnfalse;

i++;

}

returntrue;

}

}

returnfalse;

}

原來是String重寫了Object的equals方法,把引用比較改爲了值比較。

總結:==對於基本類型來講是值比較,對於引用類型來講是比較的是引用;而equals默認狀況下是引用比較,只是不少類從新了equals方法,好比String、Integer等把它變成了值比較,因此通常狀況下equals比較的是值是否相等。

3.兩個對象的hashCode()相同,則equals()也必定爲true,對嗎?

不對,兩個對象的hashCode()相同,equals()不必定true。

代碼示例:

Stringstr1="通話";

Stringstr2="重地";

System.out.println(String.format("str1:%d|str2:%d",str1.hashCode(),str2.hashCode()));

System.out.println(str1.equals(str2));

執行的結果:

str1:1179395|str2:1179395

false

代碼解讀:很顯然「通話」和「重地」的hashCode()相同,然而equals()則爲false,由於在散列表中,hashCode()相等即兩個鍵值對的哈希值相等,然而哈希值相等,並不必定能得出鍵值對相等。

4.final在Java中有什麼做用?

final修飾的類叫最終類,該類不能被繼承。

final修飾的方法不能被重寫。

final修飾的變量叫常量,常量必須初始化,初始化以後值就不能被修改。

5.Java中的Math.round(-1.5)等於多少?

等於-1,由於在數軸上取值時,中間值(0.5)向右取整,因此正0.5是往上取整,負0.5是直接捨棄。

6.String屬於基礎的數據類型嗎?

String不屬於基礎類型,基礎類型有8種:byte、boolean、char、short、int、float、long、double,而String屬於對象。

7.Java中操做字符串都有哪些類?它們之間有什麼區別?

操做字符串的類有:String、StringBuffer、StringBuilder。

String和StringBuffer、StringBuilder的區別在於String聲明的是不可變的對象,每次操做都會生成新的String對象,而後將指針指向新的String對象,而StringBuffer、StringBuilder能夠在原有對象的基礎上進行操做,因此在常常改變字符串內容的狀況下最好不要使用String。

StringBuffer和StringBuilder最大的區別在於,StringBuffer是線程安全的,而StringBuilder是非線程安全的,但StringBuilder的性能卻高於StringBuffer,因此在單線程環境下推薦使用StringBuilder,多線程環境下推薦使用StringBuffer。

8.Stringstr="i"與Stringstr=newString("i")同樣嗎?

不同,由於內存的分配方式不同。Stringstr="i"的方式,Java虛擬機會將其分配到常量池中;而Stringstr=newString("i")則會被分到堆內存中。

9.如何將字符串反轉?

使用StringBuilder或者stringBuffer的reverse()方法。

示例代碼:

//StringBufferreverse

StringBufferstringBuffer=newStringBuffer();

stringBuffer.append("abcdefg");

System.out.println(stringBuffer.reverse());//gfedcba

//StringBuilderreverse

StringBuilderstringBuilder=newStringBuilder();

stringBuilder.append("abcdefg");

System.out.println(stringBuilder.reverse());//gfedcba

10.String類的經常使用方法都有那些?

indexOf():返回指定字符的索引。

charAt():返回指定索引處的字符。

replace():字符串替換。

trim():去除字符串兩端空白。

split():分割字符串,返回一個分割後的字符串數組。

getBytes():返回字符串的byte類型數組。

length():返回字符串長度。

toLowerCase():將字符串轉成小寫字母。

toUpperCase():將字符串轉成大寫字符。

substring():截取字符串。

equals():字符串比較。

11.抽象類必需要有抽象方法嗎?

不須要,抽象類不必定非要有抽象方法。

示例代碼:

abstractclassCat{

publicstaticvoidsayHi(){

System.out.println("hi~");

}

}

上面代碼,抽象類並無抽象方法但徹底能夠正常運行。

12.普通類和抽象類有哪些區別?

普通類不能包含抽象方法,抽象類能夠包含抽象方法。

抽象類不能直接實例化,普通類能夠直接實例化。

13.抽象類能使用final修飾嗎?

不能,定義抽象類就是讓其餘類繼承的,若是定義爲final該類就不能被繼承,這樣彼此就會產生矛盾,因此final不能修飾抽象類,以下圖所示,編輯器也會提示錯誤信息:

編譯器保存圖

14.接口和抽象類有什麼區別?

實現:抽象類的子類使用extends來繼承;接口必須使用implements來實現接口。

構造函數:抽象類能夠有構造函數;接口不能有。

實現數量:類能夠實現不少個接口;可是隻能繼承一個抽象類。

訪問修飾符:接口中的方法默認使用public修飾;抽象類中的方法能夠是任意訪問修飾符。

15.Java中IO流分爲幾種?

按功能來分:輸入流(input)、輸出流(output)。

按類型來分:字節流和字符流。

字節流和字符流的區別是:字節流按8位傳輸以字節爲單位輸入輸出數據,字符流按16位傳輸以字符爲單位輸入輸出數據。

16.BIO、NIO、AIO有什麼區別?

BIO:BlockIO同步阻塞式IO,就是咱們日常使用的傳統IO,它的特色是模式簡單使用方便,併發處理能力低。

NIO:NonIO同步非阻塞IO,是傳統IO的升級,客戶端和服務器端經過Channel(通道)通信,實現了多路複用。

AIO:AsynchronousIO是NIO的升級,也叫NIO2,實現了異步非堵塞IO,異步IO的操做基於事件和回調機制。

17.Files的經常使用方法都有哪些?

Files.exists():檢測文件路徑是否存在。

Files.createFile():建立文件。

Files.createDirectory():建立文件夾。

Files.delete():刪除一個文件或目錄。

Files.copy():複製文件。

Files.move():移動文件。

Files.size():查看文件個數。

Files.read():讀取文件。

Files.write():寫入文件。

容器

18.Java容器都有哪些?

Java容器分爲Collection和Map兩大類,其下又有不少子類,以下所示:

Collection

List

ArrayList

LinkedList

Vector

Stack

Set

HashSet

LinkedHashSet

TreeSet

Map

HashMap

LinkedHashMap

TreeMap

ConcurrentHashMap

Hashtable

19.Collection和Collections有什麼區別?

Collection是一個集合接口,它提供了對集合對象進行基本操做的通用接口方法,全部集合都是它的子類,好比List、Set等。

Collections是一個包裝類,包含了不少靜態方法,不能被實例化,就像一個工具類,好比提供的排序方法:Collections.sort(list)。

20.List、Set、Map之間的區別是什麼?

List、Set、Map的區別主要體如今兩個方面:元素是否有序、是否容許元素重複。

三者之間的區別,以下表:

區別圖

21.HashMap和Hashtable有什麼區別?

存儲:HashMap運行key和value爲null,而Hashtable不容許。

線程安全:Hashtable是線程安全的,而HashMap是非線程安全的。

推薦使用:在Hashtable的類註釋能夠看到,Hashtable是保留類不建議使用,推薦在單線程環境下使用HashMap替代,若是須要多線程使用則用ConcurrentHashMap替代。

22.如何決定使用HashMap仍是TreeMap?

對於在Map中插入、刪除、定位一個元素這類操做,HashMap是最好的選擇,由於相對而言HashMap的插入會更快,但若是你要對一個key集合進行有序的遍歷,那TreeMap是更好的選擇。

23.說一下HashMap的實現原理?

HashMap基於Hash算法實現的,咱們經過put(key,value)存儲,get(key)來獲取。當傳入key時,HashMap會根據key.hashCode()計算出hash值,根據hash值將value保存在bucket裏。當計算出的hash值相同時,咱們稱之爲hash衝突,HashMap的作法是用鏈表和紅黑樹存儲相同hash值的value。當hash衝突的個數比較少時,使用鏈表不然使用紅黑樹。

24.說一下HashSet的實現原理?

HashSet是基於HashMap實現的,HashSet底層使用HashMap來保存全部元素,所以HashSet的實現比較簡單,相關HashSet的操做,基本上都是直接調用底層HashMap的相關方法來完成,HashSet不容許重複的值。

25.ArrayList和LinkedList的區別是什麼?

數據結構實現:ArrayList是動態數組的數據結構實現,而LinkedList是雙向鏈表的數據結構實現。

隨機訪問效率:ArrayList比LinkedList在隨機訪問的時候效率要高,由於LinkedList是線性的數據存儲方式,因此須要移動指針從前日後依次查找。

增長和刪除效率:在非首尾的增長和刪除操做,LinkedList要比ArrayList效率要高,由於ArrayList增刪操做要影響數組內的其餘數據的下標。

綜合來講,在須要頻繁讀取集合中的元素時,更推薦使用ArrayList,而在插入和刪除操做較多時,更推薦使用LinkedList。

26.如何實現數組和List之間的轉換?

數組轉List:使用Arrays.asList(array)進行轉換。

List轉數組:使用List自帶的toArray()方法。

代碼示例:

//listtoarray

List<String>list=newArrayList<String>();

list.add("王磊");

list.add("的博客");

list.toArray();

//arraytolist

String[]array=newString[]{"王磊","的博客"};

Arrays.asList(array);

27.ArrayList和Vector的區別是什麼?

線程安全:Vector使用了Synchronized來實現線程同步,是線程安全的,而ArrayList是非線程安全的。

性能:ArrayList在性能方面要優於Vector。

擴容:ArrayList和Vector都會根據實際的須要動態的調整容量,只不過在Vector擴容每次會增長1倍,而ArrayList只會增長50%。

28.Array和ArrayList有何區別?

Array能夠存儲基本數據類型和對象,ArrayList只能存儲對象。

Array是指定固定大小的,而ArrayList大小是自動擴展的。

Array內置方法沒有ArrayList多,好比addAll、removeAll、iteration等方法只有ArrayList有。

29.在Queue中poll()和remove()有什麼區別?

相同點:都是返回第一個元素,並在隊列中刪除返回的對象。

不一樣點:若是沒有元素poll()會返回null,而remove()會直接拋出NoSuchElementException異常。

代碼示例:

Queue<String>queue=newLinkedList<String>();

queue.offer("string");//add

System.out.println(queue.poll());

System.out.println(queue.remove());

System.out.println(queue.size());

30.哪些集合類是線程安全的?

Vector、Hashtable、Stack都是線程安全的,而像HashMap則是非線程安全的,不過在JDK1.5以後隨着Java.util.concurrent併發包的出現,它們也有了本身對應的線程安全類,好比HashMap對應的線程安全類就是ConcurrentHashMap。

31.迭代器Iterator是什麼?

Iterator接口提供遍歷任何Collection的接口。咱們能夠從一個Collection中使用迭代器方法來獲取迭代器實例。迭代器取代了Java集合框架中的Enumeration,迭代器容許調用者在迭代過程當中移除元素。

32.Iterator怎麼使用?有什麼特色?

Iterator使用代碼以下:

List<String>list=newArrayList<>();

Iterator<String>it=list.iterator();

while(it.hasNext()){

Stringobj=it.next();

System.out.println(obj);

}

Iterator的特色是更加安全,由於它能夠確保,在當前遍歷的集合元素被更改的時候,就會拋出ConcurrentModificationException異常。

33.Iterator和ListIterator有什麼區別?

Iterator能夠遍歷Set和List集合,而ListIterator只能遍歷List。

Iterator只能單向遍歷,而ListIterator能夠雙向遍歷(向前/後遍歷)。

ListIterator從Iterator接口繼承,而後添加了一些額外的功能,好比添加一個元素、替換一個元素、獲取前面或後面元素的索引位置。

34.怎麼確保一個集合不能被修改?

可使用Collections.unmodifiableCollection(Collectionc)方法來建立一個只讀集合,這樣改變集合的任何操做都會拋出Java.lang.UnsupportedOperationException異常。

示例代碼以下:

List<String>list=newArrayList<>();

list.add("x");

Collection<String>clist=Collections.unmodifiableCollection(list);

clist.add("y");//運行時此行報錯

System.out.println(list.size());

多線程

35.並行和併發有什麼區別?

並行:多個處理器或多核處理器同時處理多個任務。

併發:多個任務在同一個CPU核上,按細分的時間片輪流(交替)執行,從邏輯上來看那些任務是同時執行。

以下圖:

併發和並行

併發=兩個隊列和一臺咖啡機。

並行=兩個隊列和兩臺咖啡機。

36.線程和進程的區別?

一個程序下至少有一個進程,一個進程下至少有一個線程,一個進程下也能夠有多個線程來增長程序的執行速度。

37.守護線程是什麼?

守護線程是運行在後臺的一種特殊進程。它獨立於控制終端而且週期性地執行某種任務或等待處理某些發生的事件。在Java中垃圾回收線程就是特殊的守護線程。

38.建立線程有哪幾種方式?

建立線程有三種方式:

繼承Thread重寫run方法;

實現Runnable接口;

實現Callable接口。

39.說一下runnable和callable有什麼區別?

runnable沒有返回值,callable能夠拿到有返回值,callable能夠看做是runnable的補充。

40.線程有哪些狀態?

線程的狀態:

NEW還沒有啓動

RUNNABLE正在執行中

BLOCKED阻塞的(被同步鎖或者IO鎖阻塞)

WAITING永久等待狀態

TIMED_WAITING等待指定的時間從新被喚醒的狀態

TERMINATED執行完成

41.sleep()和wait()有什麼區別?

類的不一樣:sleep()來自Thread,wait()來自Object。

釋放鎖:sleep()不釋放鎖;wait()釋放鎖。

用法不一樣:sleep()時間到會自動恢復;wait()可使用notify()/notifyAll()直接喚醒。

42.notify()和notifyAll()有什麼區別?

notifyAll()會喚醒全部的線程,notify()以後喚醒一個線程。notifyAll()調用後,會將所有線程由等待池移到鎖池,而後參與鎖的競爭,競爭成功則繼續執行,若是不成功則留在鎖池等待鎖被釋放後再次參與競爭。而notify()只會喚醒一個線程,具體喚醒哪個線程由虛擬機控制。

43.線程的run()和start()有什麼區別?

start()方法用於啓動線程,run()方法用於執行線程的運行時代碼。run()能夠重複調用,而start()只能調用一次。

44.建立線程池有哪幾種方式?

線程池建立有七種方式,最核心的是最後一種:

newSingleThreadExecutor():它的特色在於工做線程數目被限制爲1,操做一個無界的工做隊列,因此它保證了全部任務的都是被順序執行,最多會有一個任務處於活動狀態,而且不容許使用者改動線程池實例,所以能夠避免其改變線程數目;

newCachedThreadPool():它是一種用來處理大量短期工做任務的線程池,具備幾個鮮明特色:它會試圖緩存線程並重用,當無緩存線程可用時,就會建立新的工做線程;若是線程閒置的時間超過60秒,則被終止並移出緩存;長時間閒置時,這種線程池,不會消耗什麼資源。其內部使用SynchronousQueue做爲工做隊列;

newFixedThreadPool(intnThreads):重用指定數目(nThreads)的線程,其背後使用的是無界的工做隊列,任什麼時候候最多有nThreads個工做線程是活動的。這意味着,若是任務數量超過了活動隊列數目,將在工做隊列中等待空閒線程出現;若是有工做線程退出,將會有新的工做線程被建立,以補足指定的數目nThreads;

newSingleThreadScheduledExecutor():建立單線程池,返回ScheduledExecutorService,能夠進行定時或週期性的工做調度;

newScheduledThreadPool(intcorePoolSize):和newSingleThreadScheduledExecutor()相似,建立的是個ScheduledExecutorService,能夠進行定時或週期性的工做調度,區別在於單一工做線程仍是多個工做線程;

newWorkStealingPool(intparallelism):這是一個常常被人忽略的線程池,Java8才加入這個建立方法,其內部會構建ForkJoinPool,利用Work-Stealing算法,並行地處理任務,不保證處理順序;

ThreadPoolExecutor():是最原始的線程池建立,上面1-3建立方式都是對ThreadPoolExecutor的封裝。

45.線程池都有哪些狀態?

RUNNING:這是最正常的狀態,接受新的任務,處理等待隊列中的任務。

SHUTDOWN:不接受新的任務提交,可是會繼續處理等待隊列中的任務。

STOP:不接受新的任務提交,再也不處理等待隊列中的任務,中斷正在執行任務的線程。

TIDYING:全部的任務都銷燬了,workCount爲0,線程池的狀態在轉換爲TIDYING狀態時,會執行鉤子方法terminated()。

TERMINATED:terminated()方法結束後,線程池的狀態就會變成這個。

46.線程池中submit()和execute()方法有什麼區別?

execute():只能執行Runnable類型的任務。

submit():能夠執行Runnable和Callable類型的任務。

Callable類型的任務能夠獲取執行的返回值,而Runnable執行無返回值。

47.在Java程序中怎麼保證多線程的運行安全?

方法一:使用安全類,好比Java.util.concurrent下的類。

方法二:使用自動鎖synchronized。

方法三:使用手動鎖Lock。

手動鎖Java示例代碼以下:

Locklock=newReentrantLock();

lock.lock();

try{

System.out.println("得到鎖");

}catch(Exceptione){

//TODO:handleexception

}finally{

System.out.println("釋放鎖");

lock.unlock();

}

48.多線程中synchronized鎖升級的原理是什麼?

synchronized鎖升級原理:在鎖對象的對象頭裏面有一個threadid字段,在第一次訪問的時候threadid爲空,jvm讓其持有偏向鎖,並將threadid設置爲其線程id,再次進入的時候會先判斷threadid是否與其線程id一致,若是一致則能夠直接使用此對象,若是不一致,則升級偏向鎖爲輕量級鎖,經過自旋循環必定次數來獲取鎖,執行必定次數以後,若是尚未正常獲取到要使用的對象,此時就會把鎖從輕量級升級爲重量級鎖,此過程就構成了synchronized鎖的升級。

鎖的升級的目的:鎖升級是爲了減低了鎖帶來的性能消耗。在Java6以後優化synchronized的實現方式,使用了偏向鎖升級爲輕量級鎖再升級到重量級鎖的方式,從而減低了鎖帶來的性能消耗。

49.什麼是死鎖?

當線程A持有獨佔鎖a,並嘗試去獲取獨佔鎖b的同時,線程B持有獨佔鎖b,並嘗試獲取獨佔鎖a的狀況下,就會發生AB兩個線程因爲互相持有對方須要的鎖,而發生的阻塞現象,咱們稱爲死鎖。

50.怎麼防止死鎖?

儘可能使用tryLock(longtimeout,TimeUnitunit)的方法(ReentrantLock、ReentrantReadWriteLock),設置超時時間,超時能夠退出防止死鎖。

儘可能使用Java.util.concurrent併發類代替本身手寫鎖。

儘可能下降鎖的使用粒度,儘可能不要幾個功能用同一把鎖。

儘可能減小同步的代碼塊。

51.ThreadLocal是什麼?有哪些使用場景?

ThreadLocal爲每一個使用該變量的線程提供獨立的變量副本,因此每個線程均可以獨立地改變本身的副本,而不會影響其它線程所對應的副本。

ThreadLocal的經典使用場景是數據庫鏈接和session管理等。

52.說一下synchronized底層實現原理?

synchronized是由一對monitorenter/monitorexit指令實現的,monitor對象是同步的基本實現單元。在Java6以前,monitor的實現徹底是依靠操做系統內部的互斥鎖,由於須要進行用戶態到內核態的切換,因此同步操做是一個無差異的重量級操做,性能也很低。但在Java6的時候,Java虛擬機對此進行了大刀闊斧地改進,提供了三種不一樣的monitor實現,也就是常說的三種不一樣的鎖:偏向鎖(BiasedLocking)、輕量級鎖和重量級鎖,大大改進了其性能。

53.synchronized和volatile的區別是什麼?

volatile是變量修飾符;synchronized是修飾類、方法、代碼段。

volatile僅能實現變量的修改可見性,不能保證原子性;而synchronized則能夠保證變量的修改可見性和原子性。

volatile不會形成線程的阻塞;synchronized可能會形成線程的阻塞。

54.synchronized和Lock有什麼區別?

synchronized能夠給類、方法、代碼塊加鎖;而lock只能給代碼塊加鎖。

synchronized不須要手動獲取鎖和釋放鎖,使用簡單,發生異常會自動釋放鎖,不會形成死鎖;而lock須要本身加鎖和釋放鎖,若是使用不當沒有unLock()去釋放鎖就會形成死鎖。

經過Lock能夠知道有沒有成功獲取鎖,而synchronized卻沒法辦到。

55.synchronized和ReentrantLock區別是什麼?

synchronized早期的實現比較低效,對比ReentrantLock,大多數場景性能都相差較大,可是在Java6中對synchronized進行了很是多的改進。

主要區別以下:

ReentrantLock使用起來比較靈活,可是必須有釋放鎖的配合動做;

ReentrantLock必須手動獲取與釋放鎖,而synchronized不須要手動釋放和開啓鎖;

ReentrantLock只適用於代碼塊鎖,而synchronized可用於修飾方法、代碼塊等。

volatile標記的變量不會被編譯器優化;synchronized標記的變量能夠被編譯器優化。

56.說一下atomic的原理?

atomic主要利用CAS(CompareAndWwap)和volatile和native方法來保證原子操做,從而避免synchronized的高開銷,執行效率大爲提高。

反射

57.什麼是反射?

反射是在運行狀態中,對於任意一個類,都可以知道這個類的全部屬性和方法;對於任意一個對象,都可以調用它的任意一個方法和屬性;這種動態獲取的信息以及動態調用對象的方法的功能稱爲Java語言的反射機制。

58.什麼是Java序列化?什麼狀況下須要序列化?

Java序列化是爲了保存各類對象在內存中的狀態,而且能夠把保存的對象狀態再讀出來。

如下狀況須要使用Java序列化:

想把的內存中的對象狀態保存到一個文件中或者數據庫中時候;

想用套接字在網絡上傳送對象的時候;

想經過RMI(遠程方法調用)傳輸對象的時候。

59.動態代理是什麼?有哪些應用?

動態代理是運行時動態生成代理類。

動態代理的應用有springaop、hibernate數據查詢、測試框架的後端mock、rpc,Java註解對象獲取等。

60.怎麼實現動態代理?

JDK原生動態代理和cglib動態代理。JDK原生動態代理是基於接口實現的,而cglib是基於繼承當前類的子類實現的。

對象拷貝

61.爲何要使用克隆?

克隆的對象可能包含一些已經修改過的屬性,而new出來的對象的屬性都仍是初始化時候的值,因此當須要一個新的對象來保存當前對象的「狀態」就靠克隆方法了。

62.如何實現對象克隆?

實現Cloneable接口並重寫Object類中的clone()方法。

實現Serializable接口,經過對象的序列化和反序列化實現克隆,能夠實現真正的深度克隆。

63.深拷貝和淺拷貝區別是什麼?

淺克隆:當對象被複制時只複製它自己和其中包含的值類型的成員變量,而引用類型的成員對象並無複製。

深克隆:除了對象自己被複制外,對象所包含的全部成員變量也將複製。

JavaWeb

64.JSP和servlet有什麼區別?

JSP是servlet技術的擴展,本質上就是servlet的簡易方式。servlet和JSP最主要的不一樣點在於,servlet的應用邏輯是在Java文件中,而且徹底從表示層中的html裏分離開來,而JSP的狀況是Java和html能夠組合成一個擴展名爲JSP的文件。JSP側重於視圖,servlet主要用於控制邏輯。

65.JSP有哪些內置對象?做用分別是什麼?

JSP有9大內置對象:

request:封裝客戶端的請求,其中包含來自get或post請求的參數;

response:封裝服務器對客戶端的響應;

pageContext:經過該對象能夠獲取其餘對象;

session:封裝用戶會話的對象;

application:封裝服務器運行環境的對象;

out:輸出服務器響應的輸出流對象;

config:Web應用的配置對象;

page:JSP頁面自己(至關於Java程序中的this);

exception:封裝頁面拋出異常的對象。

66.說一下JSP的4種做用域?

page:表明與一個頁面相關的對象和屬性。

request:表明與客戶端發出的一個請求相關的對象和屬性。一個請求可能跨越多個頁面,涉及多個Web組件;須要在頁面顯示的臨時數據能夠置於此做用域。

session:表明與某個用戶與服務器創建的一次會話相關的對象和屬性。跟某個用戶相關的數據應該放在用戶本身的session中。

application:表明與整個Web應用程序相關的對象和屬性,它實質上是跨越整個Web應用程序,包括多個頁面、請求和會話的一個全局做用域。

67.session和cookie有什麼區別?

存儲位置不一樣:session存儲在服務器端;cookie存儲在瀏覽器端。

安全性不一樣:cookie安全性通常,在瀏覽器存儲,能夠被僞造和修改。

容量和個數限制:cookie有容量限制,每一個站點下的cookie也有個數限制。

存儲的多樣性:session能夠存儲在Redis中、數據庫中、應用程序中;而cookie只能存儲在瀏覽器中。

68.說一下session的工做原理?

session的工做原理是客戶端登陸完成以後,服務器會建立對應的session,session建立完以後,會把session的id發送給客戶端,客戶端再存儲到瀏覽器中。這樣客戶端每次訪問服務器時,都會帶着sessionid,服務器拿到sessionid以後,在內存找到與之對應的session這樣就能夠正常工做了。

69.若是客戶端禁止cookie能實現session還能用嗎?

能夠用,session只是依賴cookie存儲sessionid,若是cookie被禁用了,可使用url中添加sessionid的方式保證session能正常使用。

70.springmvc和struts的區別是什麼?

攔截級別:struts2是類級別的攔截;springmvc是方法級別的攔截。

數據獨立性:springmvc的方法之間基本上獨立的,獨享request和response數據,請求數據經過參數獲取,處理結果經過ModelMap交回給框架,方法之間不共享變量;而struts2雖然方法之間也是獨立的,但其全部action變量是共享的,這不會影響程序運行,卻給咱們編碼和讀程序時帶來了必定的麻煩。

攔截機制:struts2有以本身的interceptor機制,springmvc用的是獨立的aop方式,這樣致使struts2的配置文件量比springmvc大。

對ajax的支持:springmvc集成了ajax,全部ajax使用很方便,只須要一個註解@ResponseBody就能夠實現了;而struts2通常須要安裝插件或者本身寫代碼才行。

71.如何避免SQL注入?

使用預處理PreparedStatement。

使用正則表達式過濾掉字符中的特殊字符。

72.什麼是XSS攻擊,如何避免?

XSS攻擊:即跨站腳本攻擊,它是Web程序中常見的漏洞。原理是攻擊者往Web頁面裏插入惡意的腳本代碼(css代碼、Javascript代碼等),當用戶瀏覽該頁面時,嵌入其中的腳本代碼會被執行,從而達到惡意攻擊用戶的目的,如盜取用戶cookie、破壞頁面結構、重定向到其餘網站等。

預防XSS的核心是必須對輸入的數據作過濾處理。

73.什麼是CSRF攻擊,如何避免?

CSRF:Cross-SiteRequestForgery(中文:跨站請求僞造),能夠理解爲攻擊者盜用了你的身份,以你的名義發送惡意請求,好比:以你名義發送郵件、發消息、購買商品,虛擬貨幣轉帳等。

防護手段:

驗證請求來源地址;

關鍵操做添加驗證碼;

在請求地址添加token並驗證。

異常

74.throw和throws的區別?

throw:是真實拋出一個異常。

throws:是聲明可能會拋出一個異常。

75.final、finally、finalize有什麼區別?

final:是修飾符,若是修飾類,此類不能被繼承;若是修飾方法和變量,則表示此方法和此變量不能在被改變,只能使用。

finally:是try{}catch{}finally{}最後一部分,表示不論發生任何狀況都會執行,finally部分能夠省略,但若是finally部分存在,則必定會執行finally裏面的代碼。

finalize:是Object類的一個方法,在垃圾收集器執行的時候會調用被回收對象的此方法。

76.try-catch-finally中哪一個部分能夠省略?

try-catch-finally其中catch和finally均可以被省略,可是不能同時省略,也就是說有try的時候,必須後面跟一個catch或者finally。

77.try-catch-finally中,若是catch中return了,finally還會執行嗎?

finally必定會執行,即便是catch中return了,catch中的return會等finally中的代碼執行完以後,纔會執行。

78.常見的異常類有哪些?

NullPointerException空指針異常

ClassNotFoundException指定類不存在

NumberFormatException字符串轉換爲數字異常

IndexOutOfBoundsException數組下標越界異常

ClassCastException數據類型轉換異常

FileNotFoundException文件未找到異常

NoSuchMethodException方法不存在異常

IOExceptionIO異常

SocketExceptionSocket異常

網絡

79.http響應碼301和302表明的是什麼?有什麼區別?

301:永久重定向。

302:暫時重定向。

它們的區別是,301對搜索引擎優化(SEO)更加有利;302有被提示爲網絡攔截的風險。

80.forward和redirect的區別?

forward是轉發和redirect是重定向:

地址欄url顯示:fowardurl不會發生改變,redirecturl會發生改變;

數據共享:forward能夠共享request裏的數據,redirect不能共享;

效率:forward比redirect效率高。

81.簡述tcp和udp的區別?

tcp和udp是OSI模型中的運輸層中的協議。tcp提供可靠的通訊傳輸,而udp則常被用於讓廣播和細節控制交給應用的通訊傳輸。

二者的區別大體以下:

tcp面向鏈接,udp面向非鏈接即發送數據前不須要創建連接;

tcp提供可靠的服務(數據傳輸),udp沒法保證;

tcp面向字節流,udp面向報文;

tcp數據傳輸慢,udp數據傳輸快;

82.tcp爲何要三次握手,兩次不行嗎?爲何?

若是採用兩次握手,那麼只要服務器發出確認數據包就會創建鏈接,但因爲客戶端此時並未響應服務器端的請求,那此時服務器端就會一直在等待客戶端,這樣服務器端就白白浪費了必定的資源。若採用三次握手,服務器端沒有收到來自客戶端的再此確認,則就會知道客戶端並無要求創建請求,就不會浪費服務器的資源。

83.說一下tcp粘包是怎麼產生的?

tcp粘包可能發生在發送端或者接收端,分別來看兩端各類產生粘包的緣由:

發送端粘包:發送端須要等緩衝區滿才發送出去,形成粘包;

接收方粘包:接收方不及時接收緩衝區的包,形成多個包接收。

84.OSI的七層模型都有哪些?

物理層:利用傳輸介質爲數據鏈路層提供物理鏈接,實現比特流的透明傳輸。

數據鏈路層:負責創建和管理節點間的鏈路。

網絡層:經過路由選擇算法,爲報文或分組經過通訊子網選擇最適當的路徑。

傳輸層:向用戶提供可靠的端到端的差錯和流量控制,保證報文的正確傳輸。

會話層:向兩個實體的表示層提供創建和使用鏈接的方法。

表示層:處理用戶信息的表示問題,如編碼、數據格式轉換和加密解密等。

應用層:直接向用戶提供服務,完成用戶但願在網絡上完成的各類工做。

85.get和post請求有哪些區別?

get請求會被瀏覽器主動緩存,而post不會。

get傳遞參數有大小限制,而post沒有。

post參數傳輸更安全,get的參數會明文限制在url上,post不會。

86.如何實現跨域?

實現跨域有如下幾種方案:

服務器端運行跨域設置CORS等於*;

在單個接口使用註解@CrossOrigin運行跨域;

使用jsonp跨域;

87.說一下JSONP實現原理?

jsonp:JSONwithPadding,它是利用script標籤的src鏈接能夠訪問不一樣源的特性,加載遠程返回的「JS函數」來執行的。

設計模式

88.說一下你熟悉的設計模式?

單例模式:保證被建立一次,節省系統開銷。

工廠模式(簡單工廠、抽象工廠):解耦代碼。

觀察者模式:定義了對象之間的一對多的依賴,這樣一來,當一個對象改變時,它的全部的依賴者都會收到通知並自動更新。

外觀模式:提供一個統一的接口,用來訪問子系統中的一羣接口,外觀定義了一個高層的接口,讓子系統更容易使用。

模版方法模式:定義了一個算法的骨架,而將一些步驟延遲到子類中,模版方法使得子類能夠在不改變算法結構的狀況下,從新定義算法的步驟。

狀態模式:容許對象在內部狀態改變時改變它的行爲,對象看起來好像修改了它的類。

89.簡單工廠和抽象工廠有什麼區別?

簡單工廠:用來生產同一等級結構中的任意產品,對於增長新的產品,無能爲力。

工廠方法:用來生產同一等級結構中的固定產品,支持增長任意產品。

抽象工廠:用來生產不一樣產品族的所有產品,對於增長新的產品,無能爲力;支持增長產品族。

Spring/SpringMVC

90.爲何要使用spring?

spring提供ioc技術,容器會幫你管理依賴的對象,從而不須要本身建立和管理依賴對象了,更輕鬆的實現了程序的解耦。

spring提供了事務支持,使得事務操做變的更加方便。

spring提供了面向切片編程,這樣能夠更方便的處理某一類的問題。

更方便的框架集成,spring能夠很方便的集成其餘框架,好比MyBatis、hibernate等。

91.解釋一下什麼是aop?

aop是面向切面編程,經過預編譯方式和運行期動態代理實現程序功能的統一維護的一種技術。

簡單來講就是統一處理某一「切面」(類)的問題的編程思想,好比統一處理日誌、異常等。

92.解釋一下什麼是ioc?

ioc:InversionofControl(中文:控制反轉)是spring的核心,對於spring框架來講,就是由spring來負責控制對象的生命週期和對象間的關係。

簡單來講,控制指的是當前對象對內部成員的控制權;控制反轉指的是,這種控制權不禁當前對象管理了,由其餘(類,第三方容器)來管理。

93.spring有哪些主要模塊?

springcore:框架的最基礎部分,提供ioc和依賴注入特性。

springcontext:構建於core封裝包基礎上的context封裝包,提供了一種框架式的對象訪問方法。

springdao:DataAccessObject提供了JDBC的抽象層。

springaop:提供了面向切面的編程實現,讓你能夠自定義攔截器、切點等。

springWeb:提供了針對Web開發的集成特性,例如文件上傳,利用servletlisteners進行ioc容器初始化和針對Web的ApplicationContext。

springWebmvc:spring中的mvc封裝包提供了Web應用的Model-View-Controller(MVC)的實現。

94.spring經常使用的注入方式有哪些?

setter屬性注入

構造方法注入

註解方式注入

95.spring中的bean是線程安全的嗎?

spring中的bean默認是單例模式,spring框架並無對單例bean進行多線程的封裝處理。

實際上大部分時候springbean無狀態的(好比dao類),全部某種程度上來講bean也是安全的,但若是bean有狀態的話(好比viewmodel對象),那就要開發者本身去保證線程安全了,最簡單的就是改變bean的做用域,把「singleton」變動爲「prototype」,這樣請求bean至關於newBean()了,因此就能夠保證線程安全了。

有狀態就是有數據存儲功能。

無狀態就是不會保存數據。

96.spring支持幾種bean的做用域?

spring支持5種做用域,以下:

singleton:springioc容器中只存在一個bean實例,bean以單例模式存在,是系統默認值;

prototype:每次從容器調用bean時都會建立一個新的示例,既每次getBean()至關於執行newBean()操做;

Web環境下的做用域:

request:每次http請求都會建立一個bean;

session:同一個httpsession共享一個bean實例;

global-session:用於portlet容器,由於每一個portlet有單獨的session,globalsession提供一個全局性的httpsession。

注意:使用prototype做用域須要慎重的思考,由於頻繁建立和銷燬bean會帶來很大的性能開銷。

97.spring自動裝配bean有哪些方式?

no:默認值,表示沒有自動裝配,應使用顯式bean引用進行裝配。

byName:它根據bean的名稱注入對象依賴項。

byType:它根據類型注入對象依賴項。

構造函數:經過構造函數來注入依賴項,須要設置大量的參數。

autodetect:容器首先經過構造函數使用autowire裝配,若是不能,則經過byType自動裝配。

98.spring事務實現方式有哪些?

聲明式事務:聲明式事務也有兩種實現方式,基於xml配置文件的方式和註解方式(在類上添加@Transaction註解)。

編碼方式:提供編碼的形式管理和維護事務。

99.說一下spring的事務隔離?

spring有五大隔離級別,默認值爲ISOLATION_DEFAULT(使用數據庫的設置),其餘四個隔離級別和數據庫的隔離級別一致:

ISOLATION_DEFAULT:用底層數據庫的設置隔離級別,數據庫設置的是什麼我就用什麼;

ISOLATIONREADUNCOMMITTED:未提交讀,最低隔離級別、事務未提交前,就可被其餘事務讀取(會出現幻讀、髒讀、不可重複讀);

ISOLATIONREADCOMMITTED:提交讀,一個事務提交後才能被其餘事務讀取到(會形成幻讀、不可重複讀),SQLserver的默認級別;

ISOLATIONREPEATABLEREAD:可重複讀,保證屢次讀取同一個數據時,其值都和事務開始時候的內容是一致,禁止讀取到別的事務未提交的數據(會形成幻讀),MySQL的默認級別;

ISOLATION_SERIALIZABLE:序列化,代價最高最可靠的隔離級別,該隔離級別能防止髒讀、不可重複讀、幻讀。

髒讀:表示一個事務可以讀取另外一個事務中還未提交的數據。好比,某個事務嘗試插入記錄A,此時該事務還未提交,而後另外一個事務嘗試讀取到了記錄A。

不可重複讀:是指在一個事務內,屢次讀同一數據。

幻讀:指同一個事務內屢次查詢返回的結果集不同。好比同一個事務A第一次查詢時候有n條記錄,可是第二次同等條件下查詢卻有n+1條記錄,這就好像產生了幻覺。發生幻讀的緣由也是另一個事務新增或者刪除或者修改了第一個事務結果集裏面的數據,同一個記錄的數據內容被修改了,全部數據行的記錄就變多或者變少了。

100.說一下springmvc運行流程?

springmvc先將請求發送給DispatcherServlet。

DispatcherServlet查詢一個或多個HandlerMapping,找處處理請求的Controller。

DispatcherServlet再把請求提交到對應的Controller。

Controller進行業務邏輯處理後,會返回一個ModelAndView。

Dispathcher查詢一個或多個ViewResolver視圖解析器,找到ModelAndView對象指定的視圖對象。

視圖對象負責渲染返回給客戶端。

101.springmvc有哪些組件?

前置控制器DispatcherServlet。

映射控制器HandlerMapping。

處理器Controller。

模型和視圖ModelAndView。

視圖解析器ViewResolver。

102.@RequestMapping的做用是什麼?

將http請求映射到相應的類/方法上。

103.@Autowired的做用是什麼?

@Autowired它能夠對類成員變量、方法及構造函數進行標註,完成自動裝配的工做,經過@Autowired的使用來消除set/get方法。

SpringBoot/SpringCloud

104.什麼是springboot?

springboot是爲spring服務的,是用來簡化新spring應用的初始搭建以及開發過程的。

105.爲何要用springboot?

配置簡單

獨立運行

自動裝配

無代碼生成和xml配置

提供應用監控

易上手

提高開發效率

106.springboot核心配置文件是什麼?

springboot核心的兩個配置文件:

bootstrap(.yml或者.properties):boostrap由父ApplicationContext加載的,比applicaton優先加載,且boostrap裏面的屬性不能被覆蓋;

application(.yml或者.properties):用於springboot項目的自動化配置。

107.springboot配置文件有哪幾種類型?它們有什麼區別?

配置文件有.properties格式和.yml格式,它們主要的區別是書法風格不一樣。

.properties配置以下:

spring.RabbitMQ.port=5672

.yml配置以下:

spring:

RabbitMQ:

port:5672

.yml格式不支持@PropertySource註解導入。

108.springboot有哪些方式能夠實現熱部署?

使用devtools啓動熱部署,添加devtools庫,在配置文件中把spring.devtools.restart.enabled設置爲true;

使用IntellijIdea編輯器,勾上自動編譯或手動從新編譯。

109.jpa和hibernate有什麼區別?

jpa全稱JavaPersistenceAPI,是Java持久化接口規範,hibernate屬於jpa的具體實現。

110.什麼是springcloud?

springcloud是一系列框架的有序集合。它利用springboot的開發便利性巧妙地簡化了分佈式系統基礎設施的開發,如服務發現註冊、配置中心、消息總線、負載均衡、斷路器、數據監控等,均可以用springboot的開發風格作到一鍵啓動和部署。

111.springcloud斷路器的做用是什麼?

在分佈式架構中,斷路器模式的做用也是相似的,當某個服務單元發生故障(相似用電器發生短路)以後,經過斷路器的故障監控(相似熔斷保險絲),向調用方返回一個錯誤響應,而不是長時間的等待。這樣就不會使得線程因調用故障服務被長時間佔用不釋放,避免了故障在分佈式系統中的蔓延。

112.springcloud的核心組件有哪些?

Eureka:服務註冊於發現。

Feign:基於動態代理機制,根據註解和選擇的機器,拼接請求url地址,發起請求。

Ribbon:實現負載均衡,從一個服務的多臺機器中選擇一臺。

Hystrix:提供線程池,不一樣的服務走不一樣的線程池,實現了不一樣服務調用的隔離,避免了服務雪崩的問題。

Zuul:網關管理,由Zuul網關轉發請求給對應的服務。

Hibernate

113.爲何要使用hibernate?

hibernate是對jdbc的封裝,大大簡化了數據訪問層的繁瑣的重複性代碼。

hibernate是一個優秀的ORM實現,不少程度上簡化了DAO層的編碼功能。

能夠很方便的進行數據庫的移植工做。

提供了緩存機制,是程序執行更改的高效。

114.什麼是ORM框架?

ORM(ObjectRelationMapping)對象關係映射,是把數據庫中的關係數據映射成爲程序中的對象。

使用ORM的優勢:提升了開發效率下降了開發成本、開發更簡單更對象化、可移植更強。

115.hibernate中如何在控制檯查看打印的SQL語句?

在Config裏面把hibernate.show_SQL設置爲true就能夠。但不建議開啓,開啓以後會下降程序的運行效率。

116.hibernate有幾種查詢方式?

三種:hql、原生SQL、條件查詢Criteria。

117.hibernate實體類能夠被定義爲final嗎?

實體類能夠定義爲final類,但這樣的話就不能使用hibernate代理模式下的延遲關聯提供性能了,因此不建議定義實體類爲final。

118.在hibernate中使用Integer和int作映射有什麼區別?

Integer類型爲對象,它的值容許爲null,而int屬於基礎數據類型,值不能爲null。

119.hibernate是如何工做的?

讀取並解析配置文件。

讀取並解析映射文件,建立SessionFactory。

打開Session。

建立事務。

進行持久化操做。

提交事務。

關閉Session。

關閉SessionFactory。

120.get()和load()的區別?

數據查詢時,沒有OID指定的對象,get()返回null;load()返回一個代理對象。

load()支持延遲加載;get()不支持延遲加載。

121.說一下hibernate的緩存機制?

hibernate經常使用的緩存有一級緩存和二級緩存:

一級緩存:也叫Session緩存,只在Session做用範圍內有效,不須要用戶干涉,由hibernate自身維護,能夠經過:evict(object)清除object的緩存;clear()清除一級緩存中的全部緩存;flush()刷出緩存;

二級緩存:應用級別的緩存,在全部Session中都有效,支持配置第三方的緩存,如:EhCache。

122.hibernate對象有哪些狀態?

臨時/瞬時狀態:直接new出來的對象,該對象還沒被持久化(沒保存在數據庫中),不受Session管理。

持久化狀態:當調用Session的save/saveOrupdate/get/load/list等方法的時候,對象就是持久化狀態。

遊離狀態:Session關閉以後對象就是遊離狀態。

123.在hibernate中getCurrentSession和openSession的區別是什麼?

getCurrentSession會綁定當前線程,而openSession則不會。

getCurrentSession事務是Spring控制的,而且不須要手動關閉,而openSession須要咱們本身手動開啓和提交事務。

124.hibernate實體類必需要有無參構造函數嗎?爲何?

hibernate中每一個實體類必須提供一個無參構造函數,由於hibernate框架要使用reflectionapi,經過調用ClassnewInstance()來建立實體類的實例,若是沒有無參的構造函數就會拋出異常。

MyBatis

125.MyBatis中#{}和${}的區別是什麼?

#{}是預編譯處理,${}是字符替換。在使用#{}時,MyBatis會將SQL中的#{}替換成「?」,配合PreparedStatement的set方法賦值,這樣能夠有效的防止SQL注入,保證程序的運行安全。

126.MyBatis有幾種分頁方式?

分頁方式:邏輯分頁和物理分頁。

邏輯分頁:使用MyBatis自帶的RowBounds進行分頁,它是一次性查詢不少數據,而後在數據中再進行檢索。

物理分頁:本身手寫SQL分頁或使用分頁插件PageHelper,去數據庫查詢指定條數的分頁數據的形式。

127.RowBounds是一次性查詢所有結果嗎?爲何?

RowBounds表面是在「全部」數據中檢索數據,其實並不是是一次性查詢出全部數據,由於MyBatis是對jdbc的封裝,在jdbc驅動中有一個FetchSize的配置,它規定了每次最多從數據庫查詢多少條數據,假如你要查詢更多數據,它會在你執行next()的時候,去查詢更多的數據。就比如你去自動取款機取10000元,但取款機每次最多能取2500元,因此你要取4次才能把錢取完。只是對於jdbc來講,當你調用next()的時候會自動幫你完成查詢工做。這樣作的好處能夠有效的防止內存溢出。

FetchSize官方相關文檔:http://t.cn/EfSE2g3

128.MyBatis邏輯分頁和物理分頁的區別是什麼?

邏輯分頁是一次性查詢不少數據,而後再在結果中檢索分頁的數據。這樣作弊端是須要消耗大量的內存、有內存溢出的風險、對數據庫壓力較大。

物理分頁是從數據庫查詢指定條數的數據,彌補了一次性所有查出的全部數據的種種缺點,好比須要大量的內存,對數據庫查詢壓力較大等問題。

129.MyBatis是否支持延遲加載?延遲加載的原理是什麼?

MyBatis支持延遲加載,設置lazyLoadingEnabled=true便可。

延遲加載的原理的是調用的時候觸發加載,而不是在初始化的時候就加載信息。好比調用a.getB().getName(),這個時候發現a.getB()的值爲null,此時會單獨觸發事先保存好的關聯B對象的SQL,先查詢出來B,而後再調用a.setB(b),而這時候再調用a.getB().getName()就有值了,這就是延遲加載的基本原理。

130.說一下MyBatis的一級緩存和二級緩存?

一級緩存:基於PerpetualCache的HashMap本地緩存,它的聲明週期是和SQLSession一致的,有多個SQLSession或者分佈式的環境中數據庫操做,可能會出現髒數據。當Sessionflush或close以後,該Session中的全部Cache就將清空,默認一級緩存是開啓的。

二級緩存:也是基於PerpetualCache的HashMap本地緩存,不一樣在於其存儲做用域爲Mapper級別的,若是多個SQLSession之間須要共享緩存,則須要使用到二級緩存,而且二級緩存可自定義存儲源,如Ehcache。默認不打開二級緩存,要開啓二級緩存,使用二級緩存屬性類須要實現Serializable序列化接口(可用來保存對象的狀態)。

開啓二級緩存數據查詢流程:二級緩存->一級緩存->數據庫。

緩存更新機制:當某一個做用域(一級緩存Session/二級緩存Mapper)進行了C/U/D操做後,默認該做用域下全部select中的緩存將被clear。

131.MyBatis和hibernate的區別有哪些?

靈活性:MyBatis更加靈活,本身能夠寫SQL語句,使用起來比較方便。

可移植性:MyBatis有不少本身寫的SQL,由於每一個數據庫的SQL能夠不相同,因此可移植性比較差。

學習和使用門檻:MyBatis入門比較簡單,使用門檻也更低。

二級緩存:hibernate擁有更好的二級緩存,它的二級緩存能夠自行更換爲第三方的二級緩存。

相關文章
相關標籤/搜索