[置頂] XWork中的容器1
來源:程序員人生 發布時間:2015-01-23 08:25:28 閱讀次數:3320次
本文是<<struts2 技術內幕>>的學習筆記
在進行面向對象編程的時候,我們不可避免地要使用繼承實現等等java提供的語法支持。但是復雜的對象關系也為對象生命周期的管理帶來了最少以下兩個問題。
1 程序運行時,應如何雙肩我們所需要的對象。
2 當創建1個對象后,如何保證與其相干聯的依賴關系也正確的被創建處理。
好在先輩們已給我們想好了前途------在程序中引入1個額外的編程元素:容器(Container)
對象的生命管理周期
首先我們得引入1個概念-----控制反轉(Inverse of Control)
甚么是控制反轉?從字面上來講大概就是
本來應當由我控制的事情,不再需要我來控制了。至于交給誰來控制,我不需要知道。
舉個例子。
public class Person{
private Car car;
public Person(Car c){
this.car=c;
}
public void drive(){
car.drive();
}
}
上面的例子很簡單吧,1個人能開車。對車的產生,需要person自己來創造。
那甚么是ioc呢?
public class Person{
private Car car;
public Person(){
//其他代碼
}
public void setCar(Car c){
this.car=c;
}
public void drive(){
car.drive();
}
}
就這么簡單
本來需要person控制的車的創建,現在不由person來控制了。就是控制反轉。
XWork容器的定義
剛才1直再說容器,現在我們就說說strtus2中的容器。
public interface Container extends Serializable {
/**
* Default dependency name.
*/
String DEFAULT_NAME = "default";
/**
* 創建類的實例,并進行注入 在上面說的person與car的例子中
* injcet的參數就應當是person
* object內部聲明有@inject的字段和方法都將被注
* 入容器所托管的對象(例如上面說的car)
*/
void inject(Object o);
<T> T inject(Class<T> implementation);
/**
* 根據type與name取得容器中的java類實例
*/
<T> T getInstance(Class<T> type, String name);
/**
* 根據type和默許的name(default)取得容器中的java類實例
*/
<T> T getInstance(Class<T> type);
/**
* 根據type取得所有注冊這個type的name
*/
Set<String> getInstanceNames(Class<?> type);
/**
* Sets the scope strategy for the current thread.
*/
void setScopeStrategy(Scope.Strategy scopeStrategy);
/**
* Removes the scope strategy for the current thread.
*/
void removeScopeStrategy();
}
接口中的方法可以分為3類
獲得對象實例 getInstance,getInstacneNames
處理對象依賴關系 inject
處理對象的作用范圍策略 setScopeStrategy,removeScopeStrategy
并且,容器是1個輔助的編程元素,它在系統中被設計為1個全局的單例的對象。
XWork容器的管轄范圍
剛才我們已初步認識了XWork容器,現在我們看看:XWork到底能管理哪些東西。
1 獲得對象實例
getInstance可以取得被容器托管的對象。那末到底哪些對象是容器所托管的呢?
看struts-default.xml里面有3類元素,是容器所托管的
1在bean節點中聲明的框架內部的對象
2在bean節點中聲明的自定義對象
3在constant節點中聲明的系統運行參數
另外還有
在Properties文件里甚么歌的系統運行參數
再換句話說,想把自定義的對象納入容器的管理范圍,只需在Sturs/XWork的配置文件里聲明便可。
2 對象的依賴注入
就像我們上面說的people與car的關系,people里面需要1個car,而car是通過容器所管理的,那末對people的注入就是container.inject(people)。
inject方法的參數都可使甚么呢?
調用XWork容器的inject方法,能夠幫助我們將容器所管理的對象(包括框架的內部元素及系統運行參數)注入到任意的對象實例中。從而建立起任意對象與框架元素溝通的橋梁。
那末系統怎樣知道people這個對象里面就需要1個car呢?
public class Person{
@Inject
private Car car;
public Person(){
//其他代碼
}
@Inject
public void setCar(Car c){
this.car=c;
}
public void drive(){
car.drive();
}
}
在person里面的car參數或setCar方法上加上 @Inject標簽
我們看看Inject標簽的定義
@Target({METHOD, CONSTRUCTOR, FIELD, PARAMETER})
@Retention(RUNTIME)
public @interface Inject {
/**
* Dependency name. Defaults to {@link Container。DEFAULT_NAME}.
*/
String value() default DEFAULT_NAME;
/**
* Whether or not injection is required. Applicable only to methods and
* fields (not constructors or parameters).
*/
boolean required() default true;
}
關于Annotation的使用參見
http://www.cnblogs.com/peida/archive/2013/04/24/3036689.html
通過容器接口進行對象操作
1 getInstance
public class DefaultUnknownHandlerManager implements UnknownHandlerManager {
protected ArrayList<UnknownHandler> unknownHandlers;
private Configuration configuration;
private Container container;
@Inject
public void setConfiguration(Configuration configuration) {
this.configuration = configuration;
build();
}
@Inject
public void setContainer(Container container) {
this.container = container;
build();
}
/**
* Builds a list of UnknowHandlers in the order specified by the configured "unknown-handler-stack".
* If "unknown-handler-stack" was not configured, all UnknowHandlers will be returned, in no specific order
*/
protected void build() {
if (configuration != null && container != null) {
List<UnknownHandlerConfig> unkownHandlerStack = configuration.getUnknownHandlerStack();
unknownHandlers = new ArrayList<UnknownHandler>();
if (unkownHandlerStack != null && !unkownHandlerStack.isEmpty()) {
//get UnknownHandlers in the specified order
// 根據1定順序獲得UnknownHandler實例
for (UnknownHandlerConfig unknownHandlerConfig : unkownHandlerStack) {
//通過容器的getInstance方法取得容器內部脫光光的type為UnknownHandler.class
//name為傳入的參數的UnknownHandler
UnknownHandler uh = container.getInstance(UnknownHandler.class, unknownHandlerConfig.getName());
unknownHandlers.add(uh);
}
} else {
//add all available UnknownHandlers
Set<String> unknowHandlerNames = container.getInstanceNames(UnknownHandler.class);
for (String unknowHandlerName : unknowHandlerNames) {
UnknownHandler uh = container.getInstance(UnknownHandler.class, unknowHandlerName);
unknownHandlers.add(uh);
}
}
}
}
.....
}
固然build方法的調用1定是在setContainer與setConfiguration調用以后。
2 inject
public class ActionSupport implements Action, Validateable, ValidationAware, TextProvider, LocaleProvider, Serializable {
private TextProvider getTextProvider() {
if (textProvider == null) {
TextProviderFactory tpf = new TextProviderFactory();
if (container != null) {
container.inject(tpf);
}
textProvider = tpf.createInstance(getClass(), this);
}
return textProvider;
}
@Inject
public void setContainer(Container container) {
this.container = container;
}
}
我們在下面可以看到container.inject(tpf)的參數,也就是TextProviderFactory里面有1個 @Inject標簽。
固然getTextProvider之前得先調用setContainer。
public class TextProviderFactory {
private TextProvider textProvider;
@Inject
public void setTextProvider(TextProvider textProvider) {
this.textProvider = textProvider;
}
.....
}
感謝glt
參考資料
http://www.cnblogs.com/peida/archive/2013/04/24/3036689.html
生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈