今每天氣不錯,我懷着自信的笑容來到某個大廠的研發中心,開啓面試的一天。首先我不是毫無準備的,什麼java併發,多線程,jvm,分佈式,數據庫都準備的妥妥的,沒想到今天的面試的主題是spring。不過還好,我也準備了...門開了,走來一位拿着mac本,戴眼鏡的年輕的小夥子,跟我差很少大吧。而後他示意我坐下,禮貌的說:「歡迎來咱們公司面試,今天咱們就聊聊spring吧」...前端
面試官:你說下什麼是spring?java
我:spring是一種輕量級開發框架,旨在提升開發人員的開發效率以及系統的可維護性。咱們通常說的spring框架指的是Spring Framework,它是不少模塊的集合,使用這些模塊能夠很方便的協助咱們開發。這些模塊是:核心容器、數據訪問/集成、Web、AOP(面向切面編程)、工具、消息和測試模塊。好比:Core Container中的Core組件是Spring全部組件的核心,Beans組件和Context組件是實現IOC和依賴注入的基礎,AOP組件用來實現面向切面編程。mysql
面試官:使用Spring框架有什麼好處呢?程序員
我:框架能更讓咱們高效的編程以及更方便的維護咱們的系統。web
面試官:那IOC與new對象有什麼區別嗎面試
我:這就是正轉與反轉的區別。傳統應用程序是由咱們本身在對象中主動控制去直接獲取依賴對象,也就是正轉。而反轉則是容器來幫助咱們建立並注入依賴對象。spring
面試官:好的,那IOC有什麼優缺點嗎?sql
我:優勢:很明顯,實現了組件之間的解耦,提升程序的靈活性和可維護性。缺點:對象生成由於是反射編程,在效率上有些損耗。但相對於IOC提升的維護性和靈活性來講,這點損耗是微不足道的,除非某對象的生成對效率要求特別高。數據庫
面試官:spring管理這麼多對象,確定須要一個容器吧。你能說下對IOC容器的理解嗎?編程
我:首先來解釋下容器:在每一個框架中都有個容器的概念,所謂的容器就是將經常使用的服務封裝起來,而後用戶只須要遵循必定的規則就能夠達到統1、靈活、安全、方便和快速的目的。
我:而後IOC容器是具備依賴注入功能的容器,負責實例化、定位、配置應用程序中的對象以及創建這些對象間的依賴。
面試官:那你能說下IOC容器是怎麼工做的嗎?
我:首先說下兩個概念。
@Test
public void testHelloWorld() {
//一、讀取配置文件實例化一個IoC容器
ApplicationContext context = new ClassPathXmlApplicationContext("helloworld.xml");
//二、從容器中獲取Bean,注意此處徹底「面向接口編程,而不是面向實現」
HelloApi helloApi = context.getBean("hello", HelloApi.class);
//三、執行業務邏輯
helloApi.sayHello();
}
複製代碼
日誌處理方式 | 實現方式 | 優缺點 |
---|---|---|
硬代碼編寫 | ||
![]() |
處理代碼相同,代碼強耦合 | |
抽離方法,代碼複用 | ||
![]() |
手動插入代碼,代碼強耦合 | |
aop | ||
![]() |
橫向的功能抽離出來造成一個獨立的模塊,低耦合 |
面試官:那你知道spring aop的原理嗎?
我:spring aop就是基於動態代理的,若是要代理的對象實現了某個接口,那麼spring aop會使用jdk proxy,去建立代理對象,而對於沒有實現接口的對象,就沒法使用jdk的動態代理,這時spring aop會使用cglib動態代理,這時候spring aop會使用cglib生成一個被代理對象的子類做爲代理。
我:關於動態代理的原理能夠參考個人這篇文章:juejin.im/post/5cea01…
面試官:那你知道Spring Aop和AspecJ Aop有什麼區別嗎?
我:Spring AOP屬於運行時加強,而AspectJ是編譯時加強。Spring Aop基於代理,而AspectJ基於字節碼操做。Spring Aop已經集成了AspectJ,AspectJ應該算得上Java生態系統中最完整的AOP框架了。AspectJ相對於Spring Aop功能更增強大,可是Spring AOP相對來講更簡單。若是咱們的切面比較少,那麼二者性能差別不大。可是,當且切面太多的話,最好選擇AspectJ,它比Spring Aop快不少。
面試官:你對Spring中的bean瞭解嗎?都有哪些做用域?
我:Spring中的Bean有五種做用域:
@Transactional
@Override
public void save(User user1, User user2) {
new Thread(() -> {
saveError(user1, user2);
System.out.println(1 / 0);
}).start();
}
複製代碼