1. 程式人生 > >為什麼使用 spring

為什麼使用 spring

1 依賴注入(DI)

 大部分的Spring的新手(我)在學習之初對依賴注入這個詞感到迷茫,事實上它並沒有那麼複雜,應用依賴注入會使得程式碼變得更簡單、更容易理解。

通常,我們開發的java應用都是由多個類組成,它們之間相互協作來完成特定的業務邏輯。每個物件之間相互聯絡,導致高度耦合的程式碼。

參考程式碼:

 

package com.spring;

public class Performer {
    private Violin violin;
    public Performer(){
        violin=new Violin();                //與Violin緊密耦合
    }
    public void play(){
        violin.play();
    }
}

class Violin extends Instrument {

    public void play() {
        System.out.println("Violin music!");
    }
}

class Instrument {
    void play(){};
}

 

上面的程式碼有個非常明顯的問題:Performer在建構函式中建立Violin,這使得Performer與Violin緊密耦合在一起,並且當演奏家需要演奏其他樂器時,就需要改寫程式碼。

 

參考程式碼:

package com.spring;

public class Performer {
    private Instrument ins;
    public Performer(Instrument ins){
        this.ins=ins;            
    }
    public void play(){
        ins.play();
    }
}

class Violin extends Instrument {

    public void play() {
        System.out.println("Violin music!");
    }
}

class Instrument {
    void play(){};
}

 

不同於之前的演奏家,這次的演奏家沒有建立樂器,而是通過建構函式將樂器通過構造引數傳入。這便是依賴注入的一種:構造器注入。

它不僅能夠演奏小提琴,無論是鋼琴、大提琴、手風琴等繼承了Instrument的子類都能作為參賽傳入。

而且它本身並不知道將會演奏什麼樂器,這與它無關。這便是依賴注入的好處-------鬆耦合

現在performer可以接受任意instrument,那我們如何將instrument傳遞給它呢(裝配)?Spring有多種裝配的方式,XML配置是最常用的一種。

在classpath下建立xml檔案:


<?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-3.0.xsd">  
    <bean id="performer" class="com.spring.Performer">
        <constructor-arg ref="violin"/>
    </bean>  
    
    <bean id="violin" class="com.spring.Violin"></bean>  
    
  
</beans>   
 

 

測試是否成功:

 

package com.spring;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class PerformerMain {

public static void main(String[] args) {

    ApplicationContext apc = new ClassPathXmlApplicationContext("spring.xml");
    Performer hello = (Performer) apc.getBean("performer");
    hello.play();
    }
}

 

 


 

2 面向切面程式設計(AOP)

AOP:允許你把遍佈應用各處的功能分離出來形成可重用的元件。

比方說,系統中的日誌、事務管理。安全服務等,通常會分散到你的每一個元件中,哪怕只是呼叫某個方法,但他依然會使你的程式碼變得混亂並且不易修改。某個元件應該只關心如何實現自身的業務邏輯,與其無關的程式碼(日誌,安全等)應該少出現甚至不出現。

 

AOP:

 

AOP使得這些元件具有更高的內聚性以及更加關注與自身業務,完全不需要涉及其他系統服務,甚至你的核心業務根本不知道它們(日誌模組,安全模組)的存在。

為了瞭解Spring中如何使用切面,我依然使用上面的列子。

我們現在需要記錄每次演奏開始的時間與結束的時間,通常我們會這麼做:

package com.spring;

import java.text.SimpleDateFormat;
import java.util.Date;

public class Performer {
    private Instrument ins;
    private Record rec;
    public Performer(Instrument ins){
        this.ins=ins;            
        this.rec=new Record();
    }
    public void play(){
        rec.starttime();
        ins.play();
        rec.endtime();
    }
}

class Record{
    private SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    public void starttime(){
        System.out.println(df.format(new Date()));
    }
    public void endtime(){
        System.out.println(df.format(new Date()));
    }
}
 

 

從上面的程式碼我們可以明顯的看出,performer應該專心演奏,而不需要去做記錄時間這種事情,這使得Performer的程式碼複雜化。

如何將Record抽象為切面呢?只需要在配置檔案中宣告就可以了:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:aop="http://www.springframework.org/schema/aop" 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-3.0.xsd
                           http://www.springframework.org/schema/aop
                           http://www.springframework.org/schema/aop/spring-aop.xsd"
     default-autowire="byName">

    <bean id="performer" class="com.spring.Performer">
        <constructor-arg ref="violin" />
    </bean>

    <bean id="violin" class="com.spring.Violin"></bean>
    <bean id="record" class="com.spring.Record"></bean>
    
    <aop:config>
        <aop:aspect ref="record">

            <aop:pointcut expression="execution(* com.spring.Performer.play(..))"  id="play"/>

            <aop:before method="starttime" pointcut-ref="play"/>
            <aop:after method="endtime" pointcut-ref="play"/>
        </aop:aspect>
    </aop:config>
</beans>   
 

 

 

 
package com.spring;

import java.text.SimpleDateFormat;
import java.util.Date;

public class Performer {

    private Instrument ins;
    public Performer(Instrument ins){
        this.ins=ins;            //與Violin緊密耦合
    }
    public void play(){
        ins.play();
    }
}

class Record{
    private SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    public void starttime(){
        System.out.println(df.format(new Date()));
    }
    public void endtime(){
        System.out.println(df.format(new Date()));
    }
}

(轉自 鄭某某i)