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教程