Spring學習隨筆(1):為什么要使用Spring



寒冷的冬天,一周兩節課,掏出買了一年沒翻過的《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) {
        // TODO Auto-generated method stub
        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()));
    }
}

運行結果:

注意:aop除了spring的包外還需要aspectJ框架的包:


 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM