Springframework 是一個為了簡化JavaEE開發而創建的一個框架,其中主要的功能為IOC。簡單說明參看Springfremework founder Rod Johnson 寫的

Introduction to Springframwork

http://www.theserverside.com/tt/articles/article.tss?l=SpringFramework

 

Sringframework總最著名的特性要數控制反轉(Inversion of Control),也叫依賴注入(Dependency Injection),詳細參看Martin Flower的文章:

Inversion of Control Containers and the Dependency Injection pattern

http://martinfowler.com/articles/injection.html

 

Ioc的來源


時代的變遷:

New 基于接口的編程 工廠方法 Ioc


我們先看一個代碼關系,例如:

TopLogic需要一個SecondLogic完成一定的業務。

SecondLogic需要TopDAO來完成數據庫訪問。


New時代:

那么一定會有這樣的代碼:

public class TopLogic{

    private SecondLogic logic ;


    public TopLogic() {

       logic = new SecondLogic();

       //以下為初始化方法調用

       logic.XXX

       ...

    }  


    public topMethod() {

       loggic.someMethod();

    }


}


public class SecondLogic{

    private TopDAO dao ;


    public SecondLogic() {

       dao = new TopDAO();

       //以下為初始化方法調用

       dao.XXX

       ...

    }  

}


在New時代,對象間的關系通過New操作符鏈接,如果你需要一個對象,簡單的New一個就好。
New的好處是非常簡單,不好的地方有兩點,第一,你不知道New了多少個,在哪里New的。
第二是,一旦對象的名字發生了變更,或者New的初始化發生了變更(更常見),所有使用到New的地方都需要修改。

基于接口的時代:
接口是服務定義,接口是類型定義:一個接口定義了一種類型(接口名字),這種類型提供
特定的服務(接口方法)。

基于接口的編程一定要講一個服務類(例如TopLogic,SecondLogic等)分成兩部分,一個用于定義服務的接口,和
一個實現了接口方法的實現類。
例如
public interface SecondLogic {
    public void someMethod();
}

public class SecondLogicImpl implements SecondLogic{
    public void someMethod() {
       ....
    }
}

在TopLogic中使用SecondLogic的時候,不需要使用SecondLogicImpl定義,而用接口定義,
只是在實例化這個類型(接口)的時候才需要實例化類的名字(SecondLogicImpl)例如:


public class TopLogic{

    private SecondLogic logic ;


    public TopLogic() {

       logic = new SecondLogicImpl();

       //以下為初始化方法調用

       logic.XXX

       ...

    }  


    public topMethod() {

       loggic.someMethod();

    }


}

通過使用基于接口的編程,減低了變量名字變更造成的影線,但是沒有降低變量初始化
過程變化的影響。

工廠方法和基于接口聯合使用
為了將變量初始化過程變化的影響變為最小,必須把變量的初始化方法風中起來,于是
產生了工廠方法

例如,我們會有SecondLogicFacotry工廠負責專門初始化SecondLogic的實例,代碼為:

public class SecondLogicFactory {
    public static SecondLogic createSecondLogic() {
       SecondLogic logic = new SecondLogicImpl();

       //以下為初始化方法調用

       logic.XXX

       ...

       return logic;
    }
}


這時,TopLogic中所有關于SecondLogic初始化的內容都被移除了,TopLogic變為:

public class TopLogic{

    private SecondLogic logic ;


    public TopLogic() {

       logic = SecondLogicFactory.createSecondLogic()

    }  


    public topMethod() {

       loggic.someMethod();

    }


}


通常上述逐步的簡化代碼變得越來越清楚。


Ioc時代(以Spring為例)

 

Ioc將所有的對象之間的關系轉移到了xml配置文件中來。
在TopLogic中聲明存儲SecondLogic的屬性

public class TopLogic{

    private SecondLogic logic ;


    public void setSecondLogic(SecondLogic logic) {
       this.logic = logic;
    }

    public TopLogic() {


    }  


    public topMethod() {

       loggic.someMethod();

    }


}


聲明變量之間的關系:

<beans>
    <bean id="secondLogic" class="com.jpleasure.teamware.logic.SecondLogic">
       <property name="XXX" value = "11111"/>
       <property name="YYY" value = "22222"/>
    </bean>
    <bean id="topLogic" class="com.jpleasure.teamware.logic.TopLogic">
       <property name="secondLogic" ref = "secondLogic"/>
    </bean>
</beans>

當我們從Spring IOC容器中取得topLogic的時候,其中的secondLogic屬性自動的通過
配置文件的配置得到了初始化。

為什么Strut2需要使用SpringFramework
在Struts2中Action是我們擴展的點,我們使用Action處理用戶提交的請求,向用戶展現數據。
為了更好的組織代碼的結構,我們一般情況下使用三層的構架:
Action → Logic → Dao
這樣如果我們手動的管理這些對象之間的關系,以方便非常的繁瑣,另外也很不利于管理
變更,所以我們更傾向于使用Spring等類似的IOC框架類管理。

如何將Springframework和Struts2結合起來
回想第一章,我們指導在Struts2中每一個對象都是靠ObjectFactory創建的,而Springframework
就是用來管理對象創佳的,我們只需要將ObjectFactory的對象創建方法改為Spring即可。

1)在struts.properties或者struts.xml文件中將objectfactory的屬性設置為spring方式:
    xml方式:
    <constant name="struts.objectFactory" value="org.apache.struts2.spring.StrutsSpringObjectFactory" />
    properties方式:
    struts.objectFactory=org.apache.struts2.spring.StrutsSpringObjectFactory
2)當然還需要將需要的Jar文件放在WEB-INF/lib目錄下
    這些文件包括:
    struts2-spring-plugin-2.0.9.jar
    spring.jar(為了省事,包含了所有的spring模塊,實際項目中可以考慮使用具體的模塊)
3)剩余的就是Springframework的配置了
    第一,告訴Spring,對象間關系的配置在那里存放
    需要在web.xml文件中添加如下內容(注意順序):
    這個Listener在應用程序啟動的時候啟動,用來讀取配置文件。
    <listener>
        <listener-class>
            org.springframework.web.context.ContextLoaderListener
        </listener-class>
    </listener>

    這個參數配置了配置文件的路徑,說明我們可以在classpath或者WEB-INF目錄下
    防止名字滿足applicationContext-*.xml格式你的文件。
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            /WEB-INF/applicationContext-*.xml,classpath*:applicationContext-*.xml
        </param-value>
    </context-param>

4)如何讓Struts2的Action和Springframework的bean管理起來?
    Struts2會根據struts.xml中配置的class名字在springframeowrk中找id相同的bean,如果找不到
    就按照普通的方式實例化Action類。
    例如:
    struts-todo.xml
        <action name="forward" method="forward"
            class="todo">
            <result name="insert">/todo/insert.jsp</result>
            <result name="update">/todo/insert.jsp</result>
            <result name="delete">/todo/insert.jsp</result>
        </action>
    applicationContext-todo.xml
        <bean id="todo" class="com.jpleasure.teamware.action.TodoAction"
            singleton="false">
        <property name="todoLogic" ref="todoLogic"></property>
        </bean>
    則class=“todo”的Action會使用com.jpleasure.teamware.action.TodoAction。

基本程序結構:
│  .classpath
│  .project
├─src
│  │  applicationContext-todo.xml
│  │  struts-todo.xml
│  │  struts.properties
│  │  struts.xml
│  │  teamware.properties
│  │ 
│  └─com
│      └─jpleasure
│          └─teamware
│              ├─action
│              ├─dao
│              ├─fw
│              ├─logic
│              ├─util
│              └─vo
└─WebContent
    │  Index.html
    │  Index.jsp
    │ 
    ├─META-INF
    │      MANIFEST.MF
    │     
    ├─todo
    │      list.jsp
    │     
    └─WEB-INF
        │  web.xml
        │ 
        └─lib
                commons-logging-1.0.4.jar
                freemarker-2.3.8.jar
                ognl-2.6.11.jar
                spring.jar
                struts2-core-2.0.9.jar
                struts2-spring-plugin-2.0.9.jar
                xwork-2.0.4.jar
               

關于Spring的內容,請參看www.springframework.org

ExtJS教程- Hibernate教程-Struts2 教程-Lucene教程