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