[置頂] XWork中的容器1
來源:程序員人生 發(fā)布時(shí)間:2015-01-23 08:25:28 閱讀次數(shù):3313次
本文是<<struts2 技術(shù)內(nèi)幕>>的學(xué)習(xí)筆記
在進(jìn)行面向?qū)ο缶幊痰臅r(shí)候,我們不可避免地要使用繼承實(shí)現(xiàn)等等java提供的語法支持。但是復(fù)雜的對(duì)象關(guān)系也為對(duì)象生命周期的管理帶來了最少以下兩個(gè)問題。
1 程序運(yùn)行時(shí),應(yīng)如何雙肩我們所需要的對(duì)象。
2 當(dāng)創(chuàng)建1個(gè)對(duì)象后,如何保證與其相干聯(lián)的依賴關(guān)系也正確的被創(chuàng)建處理。
好在先輩們已給我們想好了前途------在程序中引入1個(gè)額外的編程元素:容器(Container)
對(duì)象的生命管理周期
首先我們得引入1個(gè)概念-----控制反轉(zhuǎn)(Inverse of Control)
甚么是控制反轉(zhuǎn)?從字面上來講大概就是
本來應(yīng)當(dāng)由我控制的事情,不再需要我來控制了。至于交給誰來控制,我不需要知道。
舉個(gè)例子。
public class Person{
private Car car;
public Person(Car c){
this.car=c;
}
public void drive(){
car.drive();
}
}
上面的例子很簡(jiǎn)單吧,1個(gè)人能開車。對(duì)車的產(chǎn)生,需要person自己來創(chuàng)造。
那甚么是ioc呢?
public class Person{
private Car car;
public Person(){
//其他代碼
}
public void setCar(Car c){
this.car=c;
}
public void drive(){
car.drive();
}
}
就這么簡(jiǎn)單
本來需要person控制的車的創(chuàng)建,現(xiàn)在不由person來控制了。就是控制反轉(zhuǎn)。
XWork容器的定義
剛才1直再說容器,現(xiàn)在我們就說說strtus2中的容器。
public interface Container extends Serializable {
/**
* Default dependency name.
*/
String DEFAULT_NAME = "default";
/**
* 創(chuàng)建類的實(shí)例,并進(jìn)行注入 在上面說的person與car的例子中
* injcet的參數(shù)就應(yīng)當(dāng)是person
* object內(nèi)部聲明有@inject的字段和方法都將被注
* 入容器所托管的對(duì)象(例如上面說的car)
*/
void inject(Object o);
<T> T inject(Class<T> implementation);
/**
* 根據(jù)type與name取得容器中的java類實(shí)例
*/
<T> T getInstance(Class<T> type, String name);
/**
* 根據(jù)type和默許的name(default)取得容器中的java類實(shí)例
*/
<T> T getInstance(Class<T> type);
/**
* 根據(jù)type取得所有注冊(cè)這個(gè)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類
獲得對(duì)象實(shí)例 getInstance,getInstacneNames
處理對(duì)象依賴關(guān)系 inject
處理對(duì)象的作用范圍策略 setScopeStrategy,removeScopeStrategy
并且,容器是1個(gè)輔助的編程元素,它在系統(tǒng)中被設(shè)計(jì)為1個(gè)全局的單例的對(duì)象。
XWork容器的管轄范圍
剛才我們已初步認(rèn)識(shí)了XWork容器,現(xiàn)在我們看看:XWork到底能管理哪些東西。
1 獲得對(duì)象實(shí)例
getInstance可以取得被容器托管的對(duì)象。那末到底哪些對(duì)象是容器所托管的呢?
看struts-default.xml里面有3類元素,是容器所托管的
1在bean節(jié)點(diǎn)中聲明的框架內(nèi)部的對(duì)象
2在bean節(jié)點(diǎn)中聲明的自定義對(duì)象
3在constant節(jié)點(diǎn)中聲明的系統(tǒng)運(yùn)行參數(shù)
另外還有
在Properties文件里甚么歌的系統(tǒng)運(yùn)行參數(shù)
再換句話說,想把自定義的對(duì)象納入容器的管理范圍,只需在Sturs/XWork的配置文件里聲明便可。
2 對(duì)象的依賴注入
就像我們上面說的people與car的關(guān)系,people里面需要1個(gè)car,而car是通過容器所管理的,那末對(duì)people的注入就是container.inject(people)。
inject方法的參數(shù)都可使甚么呢?
調(diào)用XWork容器的inject方法,能夠幫助我們將容器所管理的對(duì)象(包括框架的內(nèi)部元素及系統(tǒng)運(yùn)行參數(shù))注入到任意的對(duì)象實(shí)例中。從而建立起任意對(duì)象與框架元素溝通的橋梁。
那末系統(tǒng)怎樣知道people這個(gè)對(duì)象里面就需要1個(gè)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參數(shù)或setCar方法上加上 @Inject標(biāo)簽
我們看看Inject標(biāo)簽的定義
@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;
}
關(guān)于Annotation的使用參見
http://www.cnblogs.com/peida/archive/2013/04/24/3036689.html
通過容器接口進(jìn)行對(duì)象操作
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
// 根據(jù)1定順序獲得UnknownHandler實(shí)例
for (UnknownHandlerConfig unknownHandlerConfig : unkownHandlerStack) {
//通過容器的getInstance方法取得容器內(nèi)部脫光光的type為UnknownHandler.class
//name為傳入的參數(shù)的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方法的調(diào)用1定是在setContainer與setConfiguration調(diào)用以后。
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;
}
}
我們?cè)谙旅婵梢钥吹絚ontainer.inject(tpf)的參數(shù),也就是TextProviderFactory里面有1個(gè) @Inject標(biāo)簽。
固然getTextProvider之前得先調(diào)用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
生活不易,碼農(nóng)辛苦
如果您覺得本網(wǎng)站對(duì)您的學(xué)習(xí)有所幫助,可以手機(jī)掃描二維碼進(jìn)行捐贈(zèng)