《大廠面試》京東+百度一面,不當心都拿了Offer

你知道的越多,你不知道的越多java


點贊再看,養成習慣mysql


本文 GitHub github.com/JavaFamily 已收錄,有一線大廠面試點思惟導圖,也整理了不少個人文檔,歡迎Star和完善,你們面試能夠參照考點複習,但願咱們一塊兒有點東西。git

前言

還記得我上週說的重慶郵電研二的讀者麼?github

、

知道他拿了Offer以後我也很開心,我就想把它的面試經歷和麪試題分享出來,這樣讓你們也知道,目前實習的面試大概是怎麼樣子的。面試

很優秀的是,他每次面試都會本身作總結,我一說他就直接給到了我文檔,優秀的仔,我可能知道他拿這麼多Offer的緣由了吧。算法

整個文章我原本想貼一下面試過程,而後貼下面試題就完事了,這就能夠水一篇了。sql

可是大家確定會罵我是渣男,不負責任,題目都給了還不給我答案。數據庫

我暖男來的,最後仍是給大家寫了答案,別愛我,沒結果。編程

正文

這是一個秋高氣爽的早上,Angela丙丙一如既往的睡着懶覺,呼、呼、呼的呼嚕聲忽弱忽強。設計模式

叮叮叮,⏰鬧鐘響了,Angela丙丙如往常般,閉着眼睛摸到了手機並關了,正準備呼呼大睡。

忽然一個激靈,Angela丙丙想到了什麼,「今天還有百度和京東的面試,臥*差點睡過頭」。

一眨眼的功夫,Angela丙丙已經坐在了,京東和百度一面的會議室了。(我整合了兩個公司一面的問題,作了去重)

門開了,一個大腹便便,穿着格子襯衣的中年男子,拿着一個盡是劃痕的mac向你走來,看着快禿頂的頭髮,心想着確定是尼瑪頂級架構師吧!

是否是很熟悉,是我第一篇文章的面試官
是否是很熟悉,是我第一篇文章的面試官

小夥子自我介紹下,順便把你作過的項目介紹一下。

面試官您好我叫Angela丙丙今年23歲,我來自貴州遵義,畢業於藍翔技工職業學校電子信息工程專業,今年已經工做兩年了,以前有過華爲的實習經歷,主要在nova團隊負責核心組件開發,和團隊小夥伴攻堅難題。

如今的公司是天貓國際,主要負責活動小組的研發,擔任小組的小組長,在公司一年期間,參加過大大小小活動30多場,活動爲公司帶來9次過千萬的GMV的活動,負責的項目主要是使用了微服務的設計思想和分佈式的部署方式。

常常用到的中間件有Redis,RocketMq,ElasticSearch,Logstash,Canal,、Dubbo等等,對Dubbo的源碼有着深刻的研究和看法,而且仿照Dubbo用Netty也寫了一個類Rpc框架,如今已經開源到了GitHub,而且有了2萬的Star。

而且會用業餘時間撰寫技術博客,在各大博客論壇都要 必定的粉絲量。

我對電商全部的業務流程都有一些瞭解,對線上問題處理以及性能調優都有本身的理解,對業務的研發設計流程也十分熟悉。

由於我的緣由選擇了離職,若是能有幸加入貴公司一塊兒共事,我想我能第一時間上手併產出結果,以上就是個人自我介紹,謝謝面試官。

Tip以上自我介紹所有內容都是虛構的,只是給你們一個面試自我介紹的Demo,面試題就是Angela小丙的面試題了。

Angela丙丙?簡歷上看到你作過項目組長,你在作組長以後作了那些工做,說一下你學到了那些東西。

帥氣的面試官您好,進入公司以後,我由於項目調動成爲了小組的Leader,這並無我想的爽,由於以前就是負責本身份內的事情就行了,如今須要有項目的大局觀,還有項目進度把控,已經組員的代碼和方案的Review。

小組同窗都很是優秀,我若是要Hold住他們,就得逼迫本身去不斷的學習,因此這段時光很是痛苦,可是獲得的收穫倒是實實在在的。

有看過HashMap源碼嗎?

嗯嗯這個我看過的,由於實際開發過程當中,Map仍是比較常見的面試題。

JDK1.7中HashMap的put()方法全過程。

JDK1.8有那些變化。

JDK1.7當中HashMap中線程不安全問題有那些?緣由分別是什麼?

JDK1.8以後如何鏈地址法,鏈表長度是多少的時候會轉換成紅黑樹。

節點個數是多少的時候,紅黑樹會退回鏈表。

爲何會選擇8做爲鏈表轉紅黑樹的閾值。

根據泊松分佈,在負載因子默認爲0.75的時候,單個hash槽內元素個數爲8的機率小於百萬分之一,因此將7做爲一個分水嶺,等於7的時候不轉換,大於等於8的時候才進行轉換,小於等於6的時候就化爲鏈表。

HashMap與HashTable有什麼區別?

有沒有了解過ConcurrentHashMap?

JDK1.8以後ConcurrentHashMap如何保證線程安全性?(CAS+synchronized),這裏還順便問了synchronized和可重入鎖的區別。

與JDK1.7相比有那些優化?

關於HashMap和ConcurrentHashMap的知識點我寫過了,就不作重複工做了,去看看我HashMap和ConcurrentHashMap相關的文章就行了(跟我介紹的內容基本一致,以我爲準):

說到synchronized,說些synchronized加載static關鍵字前和普通方法前的區別?

Synchronized修飾非靜態方法,其實是對調用該方法的對象加鎖,俗稱「對象鎖」

Synchronized修飾靜態方法,其實是對該類對象加鎖,俗稱「類鎖」。

  • 對象鎖鑰匙只能有一把才能互斥,才能保證共享變量的惟一性
  • 在靜態方法上的鎖,和 實例方法上的鎖,默認不是一樣的,若是同步須要制定兩把鎖同樣。
  • 關於同一個類的方法上的鎖,來自於調用該方法的對象,若是調用該方法的對象是相同的,那麼鎖必然相同,不然就不相同。好比 new A().x() 和 new A().x(),對象不一樣,鎖不一樣,若是A的單利的,就能互斥。
  • 靜態方法加鎖,能和全部其餘靜態方法加鎖的 進行互斥
  • 靜態方法加鎖,和xx.class 鎖效果同樣,直接屬於類的

看你熟悉單例,介紹下單例模式而且說下單例懶漢式和餓漢式的區別?(手寫)

單例的介紹:

意圖:保證一個類僅有一個實例,並提供一個訪問它的全局訪問點。

主要解決:一個全局使用的類頻繁地建立與銷燬。

什麼時候使用:當您想控制實例數目,節省系統資源的時候。

如何解決:判斷系統是否已經有這個單例,若是有則返回,若是沒有則建立。

關鍵代碼:構造函數是私有的。

應用實例:

  • 一個班級只有一個班主任。
  • Windows 是多進程多線程的,在操做一個文件的時候,就不可避免地出現多個進程或線程同時操做一個文件的現象,因此全部文件的處理必須經過惟一的實例來進行。
  • 一些設備管理器經常設計爲單例模式,好比一個電腦有兩臺打印機,在輸出的時候就要處理不能兩臺打印機打印同一個文件。

優勢:

  • 在內存裏只有一個實例,減小了內存的開銷,尤爲是頻繁的建立和銷燬實例(好比管理學院首頁頁面緩存)。
  • 避免對資源的多重佔用(好比寫文件操做)。

缺點:沒有接口,不能繼承,與單一職責原則衝突,一個類應該只關心內部邏輯,而不關心外面怎麼樣來實例化。

使用場景:

  • 要求生產惟一序列號。
  • WEB 中的計數器,不用每次刷新都在數據庫里加一次,用單例先緩存起來。
  • 建立的一個對象須要消耗的資源過多,好比 I/O 與數據庫的鏈接等。

注意事項:getInstance() 方法中須要使用同步鎖 synchronized (Singleton.class) 防止多線程同時進入形成 instance 被屢次實例化。

懶漢

public class Singleton {  
    private static Singleton instance;  
    private Singleton (){}  

    public static Singleton getInstance() {  
    if (instance == null) {  
        instance = new Singleton();  
    }  
    return instance;  
    }  
}
複製代碼

餓漢

public class Singleton {  
    private static Singleton instance = new Singleton();  
    private Singleton (){}  
    public static Singleton getInstance() {  
    return instance;  
    }  
}
複製代碼

懶漢式下如何保證線程安全?

public class Singleton {  
    private static Singleton instance;  
    private Singleton (){}  
    public static synchronized Singleton getInstance() {  
    if (instance == null) {  
        instance = new Singleton();  
    }  
    return instance;  
    }  
}
複製代碼

建立線程安全的單例有那些實現方法?

雙檢鎖/雙重校驗鎖(DCL,即 double-checked locking)

public class Singleton {  
    private volatile static Singleton singleton;  
    private Singleton (){}  
    public static Singleton getSingleton() {  
    if (singleton == null) {  
        synchronized (Singleton.class) {  
        if (singleton == null) {  
            singleton = new Singleton();  
        }  
        }  
    }  
    return singleton;  
    }  
}
複製代碼

登記式/靜態內部類

public class Singleton {  
    private static class SingletonHolder {  
    private static final Singleton INSTANCE = new Singleton();  
    }  
    private Singleton (){}  
    public static final Singleton getInstance() {  
    return SingletonHolder.INSTANCE;  
    }  
}
複製代碼

枚舉

public enum Singleton {  
    INSTANCE;  
    public void whateverMethod() {  
    }  
}
複製代碼

說一下JVM的內存模型?(每個模塊都說)

方法區(Method Area)
方法區主要是放一下相似類定義、常量、編譯後的代碼、靜態變量等,在JDK1.7中,HotSpot VM的實現就是將其放在永久代中,這樣的好處就是能夠直接使用堆中的GC算法來進行管理,但壞處就是常常會出現內存溢出,即PermGen Space異常,因此在JDK1.8中,HotSpot VM取消了永久代,用元空間取而代之,元空間直接使用本地內存,理論上電腦有多少內存它就可使用多少內存,因此不會再出現PermGen Space異常。

堆(Heap)
幾乎全部對象、數組等都是在此分配內存的,在JVM內存中佔的比例也是極大的,也是GC垃圾回收的主要陣地,平時咱們說的什麼新生代、老年代、永久代也是指的這片區域,至於爲何要進行分代後面會解釋。

虛擬機棧(Java Stack)
當JVM在執行方法時,會在此區域中建立一個棧幀來存放方法的各類信息,好比返回值,局部變量表和各類對象引用等,方法開始執行前就先建立棧幀入棧,執行完後就出棧。

本地方法棧(Native Method Stack)
和虛擬機棧相似,不過區別是專門提供給Native方法用的。

程序計數器(Program Counter Register)
佔用很小的一片區域,咱們知道JVM執行代碼是一行一行執行字節碼,因此須要一個計數器來記錄當前執行的行數。

熟不熟悉垃圾回收算法?給我介紹一下垃圾回收算法有哪些?

標記清除

標記-清除算法將垃圾回收分爲兩個階段:標記階段和清除階段

在標記階段首先經過根節點(GC Roots),標記全部從根節點開始的對象,未被標記的對象就是未被引用的垃圾對象。而後,在清除階段,清除全部未被標記的對象。

複製算法

從根集合節點進行掃描,標記出全部的存活對象,並將這些存活的對象複製到一起新的內存(圖中下邊的那一起內存)上去,以後將原來的那一起內存(圖中上邊的那一起內存)所有回收掉

標記整理

複製算法的高效性是創建在存活對象少、垃圾對象多的前提下的。

這種狀況在新生代常常發生,可是在老年代更常見的狀況是大部分對象都是存活對象。若是依然使用複製算法,因爲存活的對象較多,複製的成本也將很高。

分代收集算法

分代收集算法就是目前虛擬機使用的回收算法,它解決了標記整理不適用於老年代的問題,將內存分爲各個年代。通常狀況下將堆區劃分爲老年代(Tenured Generation)和新生代(Young Generation),在堆區以外還有一個代就是永久代(Permanet Generation)。

在不一樣年代使用不一樣的算法,從而使用最合適的算法,新生代存活率低,可使用複製算法。而老年代對象存活率搞,沒有額外空間對它進行分配擔保,因此只能使用標記清除或者標記整理算法。

如何斷定一個對象是否應該回收。

爲了解決循環引用的問題,java中採起了正向可達的方式,主要是經過Roots對象做爲起點進行搜索,搜索走過的路徑稱爲「引用鏈」,當一個對象到 Roots 沒有任何的引用鏈相連時時,證實此對象不可用,固然被斷定爲不可達的對象不必定就會成爲可回收對象。

被斷定爲不可達的對象要成爲可回收對象必須至少經歷兩次標記過程,若是在這兩次標記過程當中仍然沒有逃脫成爲可回收對象的可能性,則基本上就真的成爲可回收對象了,可否被回收其實主要仍是要看finalize()方法有沒有與引用鏈上的對象關聯,若是在finalize()方法中有關聯則自救成功,改對象不可被回收,反之若是沒有關聯則成功被二次標記成功,就能夠稱爲要被回收的垃圾了。

除了垃圾回收,還有那些工做會形成CPU負載太高(其實這裏給出的是一個場景,就是讓描述一下除了垃圾回收以外,還有那些工做會讓線上CPU佔用到百分之90-100,而且給出排查過程。)。

說一下CMS垃圾回收器和G1收集器的特色,和收集過程。

CMS收集器是一種以獲取最短回收停頓時間爲目標的收集器。基於「標記-清除」算法實現,它的運做過程以下:

  • 初始標記

  • 併發標記

  • 從新標記

  • 併發清除

    初始標記、重新標記這兩個步驟仍然須要「stop the world」,初始標記僅僅只是標記一下GC Roots能直接關聯到的對象,熟讀很快,併發標記階段就是進行GC Roots Tracing,而從新標記階段則是爲了修正併發標記期間因用戶程序繼續運做而致使標記產生表動的那一部分對象的標記記錄,這個階段的停頓時間通常會比初始標記階段稍長點,但遠比並發標記的時間短。
    CMS是一款優秀的收集器,主要優勢:併發收集、低停頓。

缺點:

  • CMS收集器對CPU資源很是敏感。在併發階段,它雖然不會致使用戶線程停頓,可是會由於佔用了一部分線程而致使應用程序變慢,總吞吐量會下降。

  • CMS收集器沒法處理浮動垃圾,可能會出現「Concurrent Mode Failure(併發模式故障)」失敗而致使Full GC產生。

浮動垃圾:因爲CMS併發清理階段用戶線程還在運行着,伴隨着程序運行天然就會有新的垃圾不斷產生,這部分垃圾出現的標記過程以後,CMS沒法在當次收集中處理掉它們,只好留待下一次GC中再清理。這些垃圾就是「浮動垃圾」。

  • CMS是一款「標記--清除」算法實現的收集器,容易出現大量空間碎片。當空間碎片過多,將會給大對象分配帶來很大的麻煩,每每會出現老年代還有很大空間剩餘,可是沒法找到足夠大的連續空間來分配當前對象,不得不提早觸發一次Full GC。

G1是一款面向服務端應用的垃圾收集器。G1具有以下特色:

  • 並行於併發:G1能充分利用CPU、多核環境下的硬件優點,使用多個CPU(CPU或者CPU核心)來縮短stop-The-World停頓時間。部分其餘收集器本來須要停頓Java線程執行的GC動做,G1收集器仍然能夠經過併發的方式讓java程序繼續執行。

  • 分代收集:雖然G1能夠不須要其餘收集器配合就能獨立管理整個GC堆,可是仍是保留了分代的概念。它可以採用不一樣的方式去處理新建立的對象和已經存活了一段時間,熬過屢次GC的舊對象以獲取更好的收集效果。

  • 空間整合:與CMS的「標記--清理」算法不一樣,G1從總體來看是基於「標記整理」算法實現的收集器;從局部上來看是基於「複製」算法實現的。

  • 可預測的停頓:這是G1相對於CMS的另外一個大優點,下降停頓時間是G1和CMS共同的關注點,但G1除了追求低停頓外,還能創建可預測的停頓時間模型,能讓使用者明確指定在一個長度爲M毫秒的時間片斷內,

  • G1運做步驟:

一、初始標記;二、併發標記;三、最終標記;四、篩選回收

String a = 「abc」 ; 和String b = new String(「abc」) ; 是否是同樣的?爲何? 他們對應的內存空間分別是什麼?

不同

常量池
指的是在編譯期肯定,並被保存在已編譯的字節碼文件中的一些數據,它包括類、方法、接口等中的常量,存放字符串常量和基本類型常量(public static final)。
棧(stack)

主要保存基本數據類型(或者叫內置類型)(char、byte、short、int、long、float、double、boolean)和對象的引用,數據能夠共享,速度僅次於寄存器(register),快於堆。
因此他們在 == 的時候是false

說一下JVM建立對象的過程。

常量池中定位類的符號引用

​ ↓

檢查符號引用所表明的類是否已被加載,解析和初始化過 →

​ ↓ ↓

分配內存(類加載完成後,內存需求肯定) ← 加載

​ ↓

根據java堆是否規整(GC方法)選擇分配方法

​ ↙ ↘

指針碰撞 空閒列表

​ ↓

分配內存的併發保證(指針更新的原子性)

​ ↙ ↘

CAS+失敗重試 按照線程劃分在不一樣的空間中進行TLAB -XX:+UseTLAB -XX:-UseTLAB

​ ↓

內存空間初始化爲0值,保證對象的實例字段能夠不賦初值就可使用。

​ ↓

設置對象頭信息(Object Header):引用指針,元數據,hash值,GC分代年齡,鎖相關

​ ↓

執行對象方法

說一下byte a = 127, byte b = 127; a+=b 和a = a+b的區別分別會出現什麼問題。

a+=b 會出現負數。

a=a+b 會直接報錯。

強制類型提高形成的

是否熟悉mysql? 說一下mysql的隔離級別和對應的問題。

Read Uncommitted(讀取未提交內容)

在該隔離級別,全部事務均可以看到其餘未提交事務的執行結果。本隔離級別不多用於實際應用,由於它的性能也不比其餘級別好多少。讀取未提交的數據,也被稱之爲髒讀(Dirty Read)。

Read Committed(讀取提交內容)

這是大多數數據庫系統的默認隔離級別(但不是MySQL默認的)。它知足了隔離的簡單定義:一個事務只能看見已經提交事務所作的改變。這種隔離級別 也支持所謂的不可重複讀(Nonrepeatable Read),由於同一事務的其餘實例在該實例處理其間可能會有新的commit,因此同一select可能返回不一樣結果。

Repeatable Read(可重讀)

這是MySQL的默認事務隔離級別,它確保同一事務的多個實例在併發讀取數據時,會看到一樣的數據行。不過理論上,這會致使另外一個棘手的問題:幻讀 (Phantom Read)。簡單的說,幻讀指當用戶讀取某一範圍的數據行時,另外一個事務又在該範圍內插入了新行,當用戶再讀取該範圍的數據行時,會發現有新的「幻影」 行。InnoDB和Falcon存儲引擎經過多版本併發控制(MVCC,Multiversion Concurrency Control)機制解決了該問題。

Serializable(可串行化)

這是最高的隔離級別,它經過強制事務排序,使之不可能相互衝突,從而解決幻讀問題。簡言之,它是在每一個讀的數據行上加上共享鎖。在這個級別,可能致使大量的超時現象和鎖競爭。這四種隔離級別採起不一樣的鎖類型來實現,若讀取的是同一個數據的話,就容易發生問題。例如:

  • 髒讀(Drity Read):某個事務已更新一份數據,另外一個事務在此時讀取了同一份數據,因爲某些緣由,前一個RollBack了操做,則後一個事務所讀取的數據就會是不正確的。
  • 不可重複讀(Non-repeatable read):在一個事務的兩次查詢之中數據不一致,這多是兩次查詢過程當中間插入了一個事務更新的原有的數據。
  • 幻讀(Phantom Read):在一個事務的兩次查詢中數據筆數不一致,例若有一個事務查詢了幾列(Row)數據,而另外一個事務卻在此時插入了新的幾列數據,先前的事務在接下來的查詢中,就有幾列數據是未查詢出來的,若是此時插入和另一個事務插入的數據,就會報錯。

什麼是MVCC,主要是爲了作什麼?

MVCC(Mutil-Version Concurrency Control),就是多版本併發控制。MVCC 是一種併發控制的方法,通常在數據庫管理系統中,實現對數據庫的併發訪問。

在Mysql的InnoDB引擎中就是指在已提交讀(READ COMMITTD)和可重複讀(REPEATABLE READ)這兩種隔離級別下的事務對於SELECT操做會訪問版本鏈中的記錄的過程。

這就使得別的事務能夠修改這條記錄,反正每次修改都會在版本鏈中記錄。SELECT能夠去版本鏈中拿記錄,這就實現了讀-寫,寫-讀的併發執行,提高了系統的性能。

咱們的數據庫當中如何作的優化?

  • 對查詢進行優化,要儘可能避免全表掃描,首先應考慮在 where 及 order by 涉及的列上創建索引。

  • 應儘可能避免在 where 子句中對字段進行 null 值判斷,不然將致使引擎放棄使用索引而進行全表掃描

  • 應儘可能避免在 where 子句中使用 != 或 <> 操做符,不然將引擎放棄使用索引而進行全表掃描。

  • 應儘可能避免在 where 子句中使用 or 來鏈接條件,若是一個字段有索引,一個字段沒有索引,將致使引擎放棄使用索引而進行全表掃描

  • in 和 not in 也要慎用,不然會致使全表掃描

  • like模糊全匹配也將致使全表掃描

說一下mybaits和hibernate的區別。

共同點:

MyBaits和HiBernate都是經過ORM對象關係映射框架,都是持久層數據框架。

不一樣點:

  • HiBernate它重量級的框架,而MyBaits是輕量級的框架。
  • HiBernate對JDBC的封裝比較深,對開發者些sql的能力不是很高,只須要經過Hql語句操做對象便可完成數據的持久化操做了。
  • MyBaits也是對JDBC的封裝,可是沒有Hibernate那麼深,它的sql語句,都再配置裏,能夠經過重寫配置裏sql,來實現數據優化,實施起來也比較方便。
  • 處理大數據的時候,建議使用MyBaits它優化sql語句更方便。

Hibernate狀態的轉換關係。

最新的Hibernate文檔中爲Hibernate對象定義了四種狀態(原來是三種狀態,面試的時候基本上問的也是三種狀態),分別是:瞬時態(new, or transient)、持久態(managed, or persistent)、遊離態(detached)和移除態(removed,之前Hibernate文檔中定義的三種狀態中沒有移除態),以下圖所示,就之前的Hibernate文檔中移除態被視爲是瞬時態。

  • 瞬時態:當new一個實體對象後,這個對象處於瞬時態,即這個對象只是一個保存臨時數據的內存區域,若是沒有變量引用這個對象,則會被JVM的垃圾回收機制回收。

    這個對象所保存的數據與數據庫沒有任何關係,除非經過Session的save()、saveOrUpdate()、persist()、merge()方法把瞬時態對象與數據庫關聯,並把數據插入或者更新到數據庫,這個對象才轉換爲持久態對象。

  • 持久態:持久態對象的實例在數據庫中有對應的記錄,並擁有一個持久化標識(ID)。

    對持久態對象進行delete操做後,數據庫中對應的記錄將被刪除,那麼持久態對象與數據庫記錄再也不存在對應關係,持久態對象變成移除態(能夠視爲瞬時態)。

    持久態對象被修改變動後,不會立刻同步到數據庫,直到數據庫事務提交。

  • 遊離態:當Session進行了close()、clear()、evict()或flush()後,實體對象從持久態變成遊離態,對象雖然擁有持久和與數據庫對應記錄一致的標識值,可是由於對象已經從會話中清除掉,對象不在持久化管理以內,因此處於遊離態(也叫脫管態)。

    遊離態的對象與臨時狀態對象是十分類似的,只是它還含有持久化標識。

說一下Spring的理解,IOC和AOP在項目裏是怎麼用的。

Spring是一個開源框架,處於MVC模式中的控制層,它能應對需求快速的變化,其主要緣由它有一種面向切面編程(AOP)的優點,其次它提高了系統性能,由於經過依賴倒置機制(IOC),系統中用到的對象不是在系統加載時就所有實例化,而是在調用到這個類時纔會實例化該類的對象,從而提高了系統性能。

這兩個優秀的性能使得Spring受到許多J2EE公司的青睞,如阿里裏中使用最多的也是Spring相關技術。

Spring的優勢:

  • 下降了組件之間的耦合性,實現了軟件各層之間的解耦。

  • 可使用容易提供的衆多服務,如事務管理,消息服務,日誌記錄等。

  • 容器提供了AOP技術,利用它很容易實現如權限攔截、運行期監控等功能。

Spring中AOP技術是設計模式中的動態代理模式,只需實現jdk提供的動態代理接口InvocationHandler,全部被代理對象的方法都由InvocationHandler接管實際的處理任務。

面向切面編程中還要理解切入點、切面、通知、織入等概念。

AOP的兩種實現方式,而且說一下哪個效率更高一些,爲何。

兩種方式:一種是JDK動態代理,另外一種是CGLib的方式。

JDK動態代理具體實現原理:

  • 經過實現InvocationHandlet接口建立本身的調用處理器;

  • 經過爲Proxy類指定ClassLoader對象和一組interface來建立動態代理;

  • 經過反射機制獲取動態代理類的構造函數,其惟一參數類型就是調用處理器接口類型;

  • 經過構造函數建立動態代理類實例,構造時調用處理器對象做爲參數參入;

JDK動態代理是面向接口的代理模式,若是被代理目標沒有接口那麼Spring也無能爲力,Spring經過Java的反射機制生產被代理接口的新的匿名實現類,重寫了其中AOP的加強方法。

CGLib動態代理:

CGLib是一個強大、高性能的Code生產類庫,能夠實現運行期動態擴展java類,Spring在運行期間經過 CGlib繼承要被動態代理的類,重寫父類的方法,實現AOP面向切面編程呢。

二者對比:

JDK動態代理是面向接口的。

CGLib動態代理是經過字節碼底層繼承要代理類來實現(若是被代理類被final關鍵字所修飾,那麼抱歉會失敗)。

性能:

關於二者之間的性能的話,JDK動態代理所建立的代理對象,在之前的JDK版本中,性能並非很高,雖然在高版本中JDK動態代理對象的性能獲得了很大的提高,可是他也並非適用於全部的場景。

主要體如今以下的兩個指標中:

  • CGLib所建立的動態代理對象在實際運行時候的性能要比JDK動態代理高很多,有研究代表,大概要高10倍;

  • 可是CGLib在建立對象的時候所花費的時間卻比JDK動態代理要多不少,有研究代表,大概有8倍的差距;

  • 所以,對於singleton的代理對象或者具備實例池的代理,由於無需頻繁的建立代理對象,因此比較適合採用CGLib動態代理,反正,則比較適用JDK動態代理。

說一些Spring的事務傳播機制。

傳播記住有以下幾種:

public interface TransactionDefinition {
    int PROPAGATION_REQUIRED = 0;
    int PROPAGATION_SUPPORTS = 1;
    int PROPAGATION_MANDATORY = 2;
    int PROPAGATION_REQUIRES_NEW = 3;
    int PROPAGATION_NOT_SUPPORTED = 4;
    int PROPAGATION_NEVER = 5;
    int PROPAGATION_NESTED = 6;
}
複製代碼
  • PROPAGATION_REQUIRED:若是當前沒有事務,就新建一個事務,若是已經存在一個事務中,加入到這個事務中。這是最多見的選擇。
  • PROPAGATION_SUPPORTS:支持當前事務,若是當前沒有事務,就以非事務方式執行。
  • PROPAGATION_MANDATORY:使用當前的事務,若是當前沒有事務,就拋出異常。
  • PROPAGATION_REQUIRES_NEW:新建事務,若是當前存在事務,把當前事務掛起。
  • PROPAGATION_NOT_SUPPORTED:以非事務方式執行操做,若是當前存在事務,就把當前事務掛起。
  • PROPAGATION_NEVER:以非事務方式執行,若是當前存在事務,則拋出異常。
  • PROPAGATION_NESTED:若是當前存在事務,則在嵌套事務內執行。若是當前沒有事務,則執行與PROPAGATION_REQUIRED相似的操做。

經常使用的主要有Required,RequiresNew,Nested三種。

  • Required:簡單理解就是事務方法會判斷是否存在事務,有事務就用已有的,沒有就從新開啓一個。
  • RequiresNew:簡單理解就是開啓新事務,若當前已有事務,掛起當前事務。新開啓的事務和以前的事務無關,擁有本身的鎖和隔離級別,能夠獨立提交和回滾,內層事務執行期間,外層事務掛起,內層事務執行完成後,外層事務恢復執行。
  • Nested:簡單理解就是嵌套事務,若是外部事務回滾,則嵌套事務也會回滾!!!外部事務提交的時候,嵌套它纔會被提交。嵌套事務回滾不會影響外部事務。子事務是上層事務的嵌套事務,在子事務執行以前會創建savepoint,嵌套事務的回滾會回到這個savepoint,不會形成父事務的回滾。

若是想事務一塊兒執行能夠用Required知足大部分場景,若是不想讓執行的子事務的結果影響到父事務的提交能夠將子事務設置爲RequiresNew。

你有什麼想問個人麼?

咱們京東\百度平時有技術分享這樣的活動麼?

有的你放心,技術分享咱們都會不一樣的同事輪流進行不一樣技術棧的分享。

好的,那我沒什麼問題了,期待能和您一塊兒共事。

總結

全部的題目都是粉絲提供的面試真題,我把全部的題目都查了下答案總結了一下,其實你們能夠看出,不少題目都是我平時文章寫的內容,我基本上就是跟着面試的思路寫的。

並且面試的題目都很基礎,是否是以爲京東百度的面試其實也不難,咱們好好準備下真心隨便進的那種,都是基礎,其實平時多留心下,都不須要突擊啥的。

點關注,不迷路

好了各位,以上就是這篇文章的所有內容了,我是敖丙,勵志作一名讓你們都記得住的博主,能看到這裏的人呀,都是人才

我後面會每週都更新幾篇一線互聯網大廠面試和經常使用技術棧相關的文章,很是感謝人才們能看到這裏,若是這個文章寫得還不錯,以爲「敖丙」我有點東西的話 求點贊👍 求關注❤️ 求分享👥 對暖男我來講真的 很是有用!!!

白嫖很差,創做不易,各位的支持和承認,就是我創做的最大動力,咱們下篇文章見!

敖丙 | 文 【原創】

若是本篇博客有任何錯誤,請批評指教,不勝感激 !


文章每週持續更新,能夠微信搜索「 三太子敖丙 」第一時間閱讀和催更(比博客早一到兩篇喲),本文 GitHub github.com/JavaFamily 已經收錄,有一線大廠面試點思惟導圖,也整理了不少個人文檔,歡迎Star和完善,你們面試能夠參照考點複習,但願咱們一塊兒有點東西。

相關文章
相關標籤/搜索