面試問你為什麼要用Spring怎麼答?

邊緣煩惱發表於2019-03-26

相信每個讀者在工作中,學習中都瞭解Spring怎麼使用,對於一個初級的開發工程師來說,僅僅瞭解怎麼使用,能夠很快的通過Spring來完成任務,這應該是足夠了,但是呢,如果你還想向更高的級別去前進,系統的學習,掌握它的底層原理是必不可少的。

面試問你為什麼要用Spring怎麼答?

每個人在面試的時候,Spring應該都是逃不過的關卡,能夠熟練的使用,這並不難,知道它的底層原理才是高出別人一步的地方。這篇文章就說簡單說下Spring的一些知識,希望能在面試的路上幫助到你們。

Spring是個開源框架,它被建立出來的初衷就是解決企業級應用開發的複雜性。Spring不僅僅侷限於服務端開發,任何的java應用都能借助於Spring變得更加簡單,可測試性更強,鬆耦合性更好。

為了降低Java開發的複雜性,Spring採取了一下4種關鍵策略:

  • 基於POJO的輕量級和最小侵入性程式設計;

  • 通過依賴注入和麵向介面實現鬆耦合;

  • 基於切面和慣例進行宣告式程式設計;

  • 通過切面和模板減少樣板式程式碼。

     幾乎Spring所做的任何事情,都是圍繞著以上四種策略來實現的,其核心就是:簡化java開發。
    複製程式碼

1、輕量級POJO

在日常的開發過程中,可能大部分人都感受到了,很多框架都會強迫應用繼承他們的類或者是實現他們的介面,這樣就會導致程式和框架綁死,說到這,我們的現在所用的框架就是這樣,各個模組,包括DAO,Service,都會強制性的繼承框架的中的類,應用程式和框架繫結的死死的。Spring竭力的避免因為自身的API來搞亂你的應用程式碼,Spring也不會強迫你實現他的介面或者是繼承它的類,最嚴重的也就是一個雷會使用Spring註解。Spring的非侵入式程式設計意味著這個類在Spring應用和非Spring應用中發揮著同樣的作用。

2、依賴注入

任何一個有實際意義的應用,肯定是會有多個類組成,在沒有Spring的時候,每個物件負責管理著與自己相互協作的物件的引用,這樣會導致高耦合和難以測試的程式碼。

public class Train implements Transport{
   private Water water;
   public Train() {
       water = new Water();
  }
   public void catchGoods(){
       water.waterSomthing();
  }
}
複製程式碼

可以看到上面的程式碼,Train在自己的建構函式中自己建立了 Water物件,這樣就造成了這兩個物件的緊耦合,這個火車可以運水來澆灌農田,但是如果讓這個火車來運煤供暖,可能就不太符合了。

而在單元測試的時候,我們要確保catchGoods方法執行的時候,waterSomthing也能夠執行,如果這樣來做,那就執行不了單元測試了。

耦合是具有兩面性的,一方面緊密的耦合的程式碼,難以測試,難以服用,難以理解,修改了一處就可能會引起別的bug(記得剛去公司的時候,講開發規範,一個介面儘量的只做一件事情,千萬不要一個介面同時為多個地方提供服務),另一方面呢完全沒有耦合的程式碼也什麼都幹不了。

有了Spring之後,物件的依賴關係由負責協調各物件的第三方元件來完成,物件無需自行建立,依賴注入會將所依賴的關係自動交給目標物件,而不是讓物件自己去獲取。

public class Train implements Transport{
   private Water water;
   public Train(Water water) {
       this.water = water;
  }
   public void catchGoods(){
       water.waterSomthing();
  }
}
複製程式碼

上面在我們的改動之後,不再由Train自行建立,而是當成一個構造器引數傳進來,這也是依賴注入的一種方式:構造器注入。這也就實現了鬆耦合。

建立應用元件之間協作的行為通常稱為裝配,Spring有著多種裝配bean的方式,XML就是一種常用的方式。

<?xml version="1.0" encoding="UTF-8"?>
<!--DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd" -->
<beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">

   <bean id="train" class="com.kr.caption.spring.Train">
       <constructor-arg ref="water"/>
   </bean>
   <bean id="water" class="com.kr.caption.spring.Water"/>
</beans>
複製程式碼

在上面的xml檔案中,兩個物件被宣告為了Spring中的bean,在Train中,在構造時傳入了對Water的引用,作為構造器引數。

@Configuration
public class TrainConfig {
   @Bean
   public Transport train(){
       return new Train(water());
  }
   @Bean
   public Water water(){
       return new Water();
  }
}
複製程式碼

上面的是基於java的配置,這兩種配置都是一樣的效果。

Spring通過應用的上下文,來裝載bean的定義,並把他們組裝起來,Spring應用上下文全權負責物件的建立和組裝,Spring有多種上下文的實現,它們之間主要的區別僅僅在於如何載入配置。

public class application {
   public static void main(String[] args) {
       ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:application_example.xml");
       Train bean = context.getBean(Train.class);
       bean.catchGoods();
  }
}
複製程式碼

這裡的main方法基於application_example.xml建立了一個Spring應用上下文,隨後就能得到一個例項物件,直接呼叫方法即可。

3、面向切面程式設計

系統由不同的元件組成,而這些元件除了實現自身的核心功能外,還承擔著其他的一些職責。比如日誌、事務管理和安全這些通常會貫穿著整個專案中的各個元件。如果沒有系統性的處理這部分,那麼你的程式碼會含有大量的重複程式碼。如果你把這些單獨抽象為一個模組,其他模組只是呼叫它的方法,方法的呼叫還是會出現各個模組。

AOP會使這些服務模組化,以宣告的方式應用到它們需要影響的模組去,這樣其他的模組就會只關注它們自身的業務,完全不需要了解這些服務的相關邏輯和程式碼。

面試問你為什麼要用Spring怎麼答?

看到上面的圖片,我們可以把切面想象為覆蓋在很多元件上的一個外殼,藉助AOP可以使那些功能層去包裹核心業務層,這些功能層以宣告的方式靈活的應用到系統中,其他的業務應用根本不知道它的存在。

寫在最後

這裡沒有太多的花言巧語,如果本文對你有所幫助,希望點選下面的二維碼關注一波,或者是朋友圈分享一下,點個好看也是棒棒的。

這樣的分享我會一直持續,你的關注、轉發和好看是對我最大的支援,感謝。

面試問你為什麼要用Spring怎麼答?

相關文章