從新來認識你的老朋友Spring框架

歡迎查看Java開發之上帝之眼系列教程,若是您正在爲Java後端龐大的體系所困擾,若是您正在爲各類繁出不窮的技術和各類框架所迷茫,那麼本系列文章將帶您窺探Java龐大的體系。本系列教程但願您能站在上帝的角度去觀察(瞭解)Java體系。使Java的各類後端技術在你心中模塊化;讓你在工做中能將Java各個技術瞭然於心;可以即插即用。本章咱們來一塊兒瞭解你的老朋友Spring框架。
 
 
Spring這個詞對於開發者想必不會陌生,可能你天天都在使用Spring,享受着Spring生態提供的服務,理所固然的用着SpringIOC和SpringAOP去實現老闆交給你的功能  ,唔  它就是這樣使用的(類聲明爲Bean組件,而後注入),沒錯 能完成老闆任務,沒毛病。若是向你提問什麼是Spring,Spring有什麼核心功能呢,你會想:這太簡單了,Spring就是框架嘛,Spring核心功能就是IOC和AOP,So Easy!!但是你真的瞭解Spring嗎?帶着這個疑問讓咱們一塊兒來從新瞭解一下Spring! 本文全部示例源碼下載
 

Spring的起源和根本使命

Spring是一個開源框架,最先由Rod Johnson建立,是爲了解決企業級應用開發的複雜性而建立的。不少框架都宣稱在某些方面針對Java開發作出了簡化,可是Spring的目標是致力於全方位簡化Java開發,這也是Spring的根本使命 "簡化Java開發"

Spring如何簡化Java開發

爲了下降Java開發的複雜性,Spring採起了如下4種關鍵策略,請務必牢記下面4中策略於心,這樣會幫助你更深的理解Spring。下面咱們來逐一解讀每一條策略,你就能明白Spring是如何簡化Java開發的。
  • 基於POJO的輕量級和最小侵入性編程
  • 經過依賴注入和麪向接口實現鬆耦合
  • 基於切面和慣例進行聲明式編程
  • 經過切面和模板減小樣版式代碼

1. 基於POJO的輕量級和最小侵入性編程

Spring竭力避免因自身的API而弄亂你的代碼。Spring不會強迫你實現Spring規範的接口或繼承Spring規範的類。相反,在一個基於Spring構建的應用中,應用中的類沒有任何痕跡代表你使用了Spring。最壞的狀況就是你在應用的類中發現了Spring的相關注解,但它依然是POJO,下面咱們來看一個在Spring中的一個POJO例子。 example1實例源碼下載
/**
 * @Author:jimisun
 * @Description:
 * @Date:Created in 20:32 2018-09-26
 * @Modified By:
 */
public class HelloSpringBean {
    public String sayHello() {
        return "Hello Spring!!!";
    }
}

 你能夠看到,這就是一個POJO(簡單的JAVA類),沒有任何地方代表它是Spring組件,Spring非侵入式編程模型意味着這個類在Spring應用和非Spring應用中均可以發揮一樣的做用。儘管看起來很簡單;但Spring經過IOC(Inversion of Control)管理這個POJO,而後經過DI(Dependency Inject)來注入他們,這個POJO就變的魔力十足;那麼DI是如何幫助應用對象彼此之間保持鬆耦合的呢?html

 

2. 經過依賴注入和麪向接口實現鬆耦合

來咱們一塊兒來看一下一個簡單的POJO   example2實例源碼下載
/**
 * @Author:jimisun
 * @Description:
 * @Date:Created in 07:44 2018-09-27
 * @Modified By:
 */
public class BeautifulGirl implements Gril {

    private EatAction eat;
public BeautifulGirl() { this.eat = new EatAction(); } @Override public void action() { eat.action(); } }

 在BeautifulGirl(可愛的小女孩)這個類中,在構造方法中建立一個EatAction(吃飯動做)。這樣就極大限制了BeautifulGirl(可愛的小女孩)的能力;若是如今小女孩須要去玩耍呢?或者須要去睡覺呢?真是太抱歉了,BeautifulGirl(可愛的小女孩)只會吃東西這個動做。這是什麼緣由呢?這就是BeautifulGirl(可愛的小女孩)和EatAction(吃飯動做)這兩個類牢牢耦合在了一塊兒!緊密耦合同時會形成代碼的難以測試,難以服用,難以理解,而且典型地表現出"打地鼠「式的Bug特性(修復一個Bug,將會出現一個或多個新Bug),因此咱們能夠知道耦合是必須的,但必須謹慎管理耦合,可是怎麼纔算是謹慎處理耦合關係呢?java

上圖所示, DI(依賴注入)會將所依賴關係自動交給目標對象,而不是讓對象自己建立所依賴對象。對象的依賴關係將由系統中負責協調個對象依賴關係的第三方組件(相似Spring)在建立對象的時候設定。如今咱們明白了經過DI依賴注入能夠將對象之間依賴關係輕鬆解耦,那麼咱們來看一下簡單的實例吧。  example3實例源碼下載
/**
 * @Author:jimisun
 * @Description:
 * @Date:Created in 07:44 2018-09-27
 * @Modified By:
 */
public class BeautifulGirl implements Gril {

    private Action action;


    public BeautifulGirl(Action action) {
        this.action = action;
    }

    @Override
    public void action() {
        action.action();
    }
}

 從上面實例代碼中能夠看到BeautifulGirl自己並無建立任何的動做,而是經過構造方法傳入一個實現了Action(動做)接口的實現類便可,也就是說BeautifulGirl能夠完成任意實現了Action接口的動做(睡覺啦...玩耍啦...旅行啦....)。這裏的要點是BeautifulGirl沒有與任何特定的Action發生耦合。BeautifulGirl只須要的是一個實現Action接口就行,對象自己只是經過接口(而非具體實現或初始化過程)來代表依賴關係,那麼這種依賴就可以在BeautifulGirl不知情的狀況下替換不一樣的具體動做。好了咱們如今明白了DI進行依關係解耦的原理了,下面咱們看一下如何在Spring中應用DI。 example4實例源碼下載git

<?xml version="1.0" encoding="UTF-8"?>
<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-4.0.xsd">

    <bean class="com.jimisun.spring.example4.BeautifulGirl" id="beautifulGirl">
        <constructor-arg ref="action"/>
    </bean>

    <bean class="com.jimisun.spring.example4.SleepAction" id="action"></bean>

</beans>
/**
 * @Author:jimisun
 * @Description:
 * @Date:Created in 07:53 2018-09-27
 * @Modified By:
 */
public class Main {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("Spring.xml");
        BeautifulGirl beautifulGirl = (BeautifulGirl) context.getBean("beautifulGirl");
        beautifulGirl.action();
        context.close();
    }
}

這樣執行Main方法,從Context中獲取BeautifulGirl實例執行action方法。固然Spring提供了基於Java的配置,可做爲XML配置文件的代替方案 example5實例源碼下載github

/**
 * @Author:jimisun
 * @Description:
 * @Date:Created in 08:40 2018-09-27
 * @Modified By:
 */
@Configuration
public class SpringConfig {

    @Bean
    public SleepAction sleepAction() {
        return new SleepAction();
    }

    @Bean
    public BeautifulGirl beautifulGirl() {
        return new BeautifulGirl(sleepAction());
    }
}
只不過Spring的上下文的實現應該使用AnnotationConfigApplicationContext進行加載配置

/**
 * @Author:jimisun
 * @Description:
 * @Date:Created in 07:53 2018-09-27
 * @Modified By:
 */
public class Main {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);
        SleepAction action = applicationContext.getBean(SleepAction.class);
        action.action();
    }
}

 

3. 基於切面和慣例進行聲明式編程

如今咱們已經明白DI可以將互相協做的軟件保持鬆耦合,而面向切面編程(aspect-oriented-programming,AOP)能夠將遍及應用各處的功能分離出來造成可從用的組件。咱們仍然使用上面的例子,BeautifulGirl爲所欲爲的執行各類動做真的沒問題嗎?若是可愛的小女孩執行的動做是去河邊玩耍,吃一些危險的東西呢?那麼咱們勢必須要一個家長(Parent類)進行監督小女孩的動做是不是安全的,下面咱們來看一下Parent類。 example6實例源碼下載
/**
 * @Author:jimisun
 * @Description:
 * @Date:Created in 09:32 2018-09-27
 * @Modified By:
 */
public class Parent {
    public void check() {
        System.out.println("檢查動做是否安全.......");
    }
}

 很是簡單!Parent(家長類)只有一個方法就是check,那麼如今就讓Parent對BeautifulGirl的執行動做進行檢查吧。spring

 <bean class="com.jimisun.spring.example6.BeautifulGirl" id="beautifulGirl">
        <constructor-arg ref="action"/>
        <constructor-arg ref="parent"/>
    </bean>

    <bean class="com.jimisun.spring.example6.SleepAction" id="action"></bean>
    <bean class="com.jimisun.spring.example6.Parent" id="parent"></bean>
</beans>
/**
 * @Author:jimisun
 * @Description:
 * @Date:Created in 07:44 2018-09-27
 * @Modified By:
 */
public class BeautifulGirl implements Girl {

    private Action action;

    private Parent parent;

    public BeautifulGirl(Action action, Parent parent) {
        this.action = action;
        this.parent = parent;
    }

    @Override
    public void action() {
        parent.check();
        action.action();
    }
}
咱們很是聰明,使用了DI將Parent類注入到了BeautifulGirl類中,在BeautifulGirl執行action動做以前執行 parent.check()方法,這樣咱們要的效果就達到了。等等....好像有什麼不對的地方?
  • 管理Parent家長的check動做真的是美麗的小女孩的職責嗎?
  • 將Parent家長注入到美麗的小女孩類中不是將代碼複雜化了嗎?
  • 咱們需不須要一個不須要家長注入的美麗的小女孩呢?
  • 若是注入的Parent爲NULL咱們是否應該在美麗的小女孩中進行校驗呢?

 

真的是太糟糕了,注入一個Parent(家長)將會產生那麼多的問題,爲何呢? 由於Parent類的業務於BeautifulGirl無關;BeautifulGirl將會承擔Parent類的職責。
 
在一個項目中,不少系統服務都會分佈到各個業務模塊中,這使得業務模塊的邏輯變得十分複雜,而使用AOP可以使這些服務模塊化,並以聲明式的方式將他們應用到他們所須要影響的組件中,使得這些組件將會具備更高的內聚性而且更加關注自身的業務邏輯,徹底不須要了解系統服務所帶來的複雜性。
下面咱們使用SpringAOP對上面代碼進行改造   example7實例源碼下載
  <!--聲明Bean-->
    <bean class="com.jimisun.spring.example7.Parent" id="parent"></bean>

    <!--聲明切面-->
    <aop:config>
        <aop:aspect ref="parent">
            <aop:pointcut id="girlAction" expression="execution(* com.jimisun.spring.example7.Action.*(..))"/>
            <aop:before pointcut-ref="girlAction" method="check"/>
        </aop:aspect>
    </aop:config>

 

/**
 * @Author:jimisun
 * @Description:
 * @Date:Created in 07:44 2018-09-27
 * @Modified By:
 */
public class BeautifulGirl implements Girl {

    private Action action;
    
    public BeautifulGirl(Action action) {
        this.action = action;
    }

    @Override
    public void girlAction() {
        action.action();
    }
}
咱們只須要在Spring配置文件中聲明Parent爲Spring Bean,而後將配置在SpringAOP中便可, 咱們能夠發現BeautifulGirl類中沒有發現任何關於Parent的信息,這就是AOP的魅力所在—— 以聲明的方式將組件應用到他們所須要影響的組件中!
 

4. 經過切面和模板減小樣版式代碼

在經過JavaAPI進行編程,咱們常常會編寫不少重複的代碼例如JDBC訪問數據庫,JMS,JNDI等場景下會重複編寫大量的樣版式代碼,而Spring皆在經過模板封裝來消除模板式代碼,例如Spring針對JDBC訪問數據庫進行封裝的JdbcTemplate等,這裏就是Spring使用封裝的模板來減小JavaAPI樣版式代碼。 example8實例源碼下載

/**
 * @Author:jimisun
 * @Description:
 * @Date:Created in 11:13 2018-09-27
 * @Modified By:
 */
public class Main {
    public static void main(String[] args) {
        JdbcTemplate jdbcTemplate = new JdbcTemplate();
        jdbcTemplate.execute("select * from user");
    }
}

 

 
 
很是感謝你們耐心能看到這裏,在本文中我儘量地詳細闡述Spring使如何簡化Java開發?遵循哪些策略?以及爲何遵循的好處。
 
 
 

本文資料來源:

 

 


 

勘誤&感謝

  本系列文章資料來源不少出自於互聯網和在下自己的看法,受限於我的技術能力水平和其餘相關知識的限制,相關看法錯誤或者資料引用錯誤請各位幫助留言校訂!引用資料多來自於互聯網,在下在引用前會遵循各位前輩或者博主的引用說明表示感謝,但互聯網資料可能是轉發再轉發或存在遺漏請原做者內信聯繫指正。

相關文章
相關標籤/搜索