Springframework 是一個(gè)為了簡(jiǎn)化JavaEE開發(fā)而創(chuàng)建的一個(gè)框架,其中主要的功能為IOC。簡(jiǎn)單說明參看Springfremework 的founder Rod Johnson 寫的
《Introduction to Springframwork》
http://www.theserverside.com/tt/articles/article.tss?l=SpringFramework
Sringframework總最著名的特性要數(shù)控制反轉(zhuǎn)(Inversion of Control),也叫依賴注入(Dependency Injection),詳細(xì)參看Martin Flower的文章:
《Inversion of Control Containers and the Dependency Injection pattern》
http://martinfowler.com/articles/injection.html
Ioc的來源
時(shí)代的變遷:
New → 基于接口的編程 → 工廠方法 → Ioc
我們先看一個(gè)代碼關(guān)系,例如:
TopLogic需要一個(gè)SecondLogic完成一定的業(yè)務(wù)。
SecondLogic需要TopDAO來完成數(shù)據(jù)庫訪問。
New時(shí)代:
那么一定會(huì)有這樣的代碼:
public class TopLogic{
private SecondLogic logic ;
public TopLogic() {
logic = new SecondLogic();
//以下為初始化方法調(diào)用
logic.XXX
...
}
public topMethod() {
loggic.someMethod();
}
}
public class SecondLogic{
private TopDAO dao ;
public SecondLogic() {
dao = new TopDAO();
//以下為初始化方法調(diào)用
dao.XXX
...
}
}
在New時(shí)代,對(duì)象間的關(guān)系通過New操作符鏈接,如果你需要一個(gè)對(duì)象,簡(jiǎn)單的New一個(gè)就好。
New的好處是非常簡(jiǎn)單,不好的地方有兩點(diǎn),第一,你不知道New了多少個(gè),在哪里New的。
第二是,一旦對(duì)象的名字發(fā)生了變更,或者New的初始化發(fā)生了變更(更常見),所有使用到New的地方都需要修改。
基于接口的時(shí)代:
接口是服務(wù)定義,接口是類型定義:一個(gè)接口定義了一種類型(接口名字),這種類型提供
特定的服務(wù)(接口方法)。
基于接口的編程一定要講一個(gè)服務(wù)類(例如TopLogic,SecondLogic等)分成兩部分,一個(gè)用于定義服務(wù)的接口,和
一個(gè)實(shí)現(xiàn)了接口方法的實(shí)現(xiàn)類。
例如
public interface SecondLogic {
public void someMethod();
}
public class SecondLogicImpl implements SecondLogic{
public void someMethod() {
....
}
}
在TopLogic中使用SecondLogic的時(shí)候,不需要使用SecondLogicImpl定義,而用接口定義,
只是在實(shí)例化這個(gè)類型(接口)的時(shí)候才需要實(shí)例化類的名字(SecondLogicImpl)例如:
public class TopLogic{
private SecondLogic logic ;
public TopLogic() {
logic = new SecondLogicImpl();
//以下為初始化方法調(diào)用
logic.XXX
...
}
public topMethod() {
loggic.someMethod();
}
}
過程變化的影響。
工廠方法和基于接口聯(lián)合使用
為了將變量初始化過程變化的影響變?yōu)樽钚。仨毎炎兞康某跏蓟椒L(fēng)中起來,于是
產(chǎn)生了工廠方法
例如,我們會(huì)有SecondLogicFacotry工廠負(fù)責(zé)專門初始化SecondLogic的實(shí)例,代碼為:
public class SecondLogicFactory {public static SecondLogic createSecondLogic() {
SecondLogic logic = new SecondLogicImpl();
//以下為初始化方法調(diào)用
logic.XXX
...
return logic;}
}
public class TopLogic{
private SecondLogic logic ;
public TopLogic() {
logic = SecondLogicFactory.createSecondLogic()
}
public topMethod() {
loggic.someMethod();
}
}
通常上述逐步的簡(jiǎn)化代碼變得越來越清楚。
在TopLogic中聲明存儲(chǔ)SecondLogic的屬性
public class TopLogic{
private SecondLogic logic ;
public void setSecondLogic(SecondLogic logic) {
this.logic = logic;
}
public TopLogic() {
}
public topMethod() {
loggic.someMethod();
}
}
聲明變量之間的關(guān)系:
<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>
當(dāng)我們從Spring IOC容器中取得topLogic的時(shí)候,其中的secondLogic屬性自動(dòng)的通過
配置文件的配置得到了初始化。
為什么Strut2需要使用SpringFramework
在Struts2中Action是我們擴(kuò)展的點(diǎn),我們使用Action處理用戶提交的請(qǐng)求,向用戶展現(xiàn)數(shù)據(jù)。
為了更好的組織代碼的結(jié)構(gòu),我們一般情況下使用三層的構(gòu)架:
Action → Logic → Dao
這樣如果我們手動(dòng)的管理這些對(duì)象之間的關(guān)系,以方便非常的繁瑣,另外也很不利于管理
變更,所以我們更傾向于使用Spring等類似的IOC框架類管理。
如何將Springframework和Struts2結(jié)合起來
回想第一章,我們指導(dǎo)在Struts2中每一個(gè)對(duì)象都是靠ObjectFactory創(chuàng)建的,而Springframework
就是用來管理對(duì)象創(chuàng)佳的,我們只需要將ObjectFactory的對(duì)象創(chuàng)建方法改為Spring即可。
1)在struts.properties或者struts.xml文件中將objectfactory的屬性設(shè)置為spring方式:
xml方式:
<constant name="struts.objectFactory" value="org.apache.struts2.spring.StrutsSpringObjectFactory" />
properties方式:
struts.objectFactory=org.apache.struts2.spring.StrutsSpringObjectFactory
2)當(dāng)然還需要將需要的Jar文件放在WEB-INF/lib目錄下
這些文件包括:
struts2-spring-plugin-2.0.9.jar
spring.jar(為了省事,包含了所有的spring模塊,實(shí)際項(xiàng)目中可以考慮使用具體的模塊)
3)剩余的就是Springframework的配置了
第一,告訴Spring,對(duì)象間關(guān)系的配置在那里存放
需要在web.xml文件中添加如下內(nèi)容(注意順序):
這個(gè)Listener在應(yīng)用程序啟動(dòng)的時(shí)候啟動(dòng),用來讀取配置文件。
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
這個(gè)參數(shù)配置了配置文件的路徑,說明我們可以在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會(huì)根據(jù)struts.xml中配置的class名字在springframeowrk中找id相同的bean,如果找不到
就按照普通的方式實(shí)例化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會(huì)使用com.jpleasure.teamware.action.TodoAction。
基本程序結(jié)構(gòu):
│ .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
關(guān)于Spring的內(nèi)容,請(qǐng)參看www.springframework.org
ExtJS教程- Hibernate教程-Struts2 教程-Lucene教程