string scopename = mergedbeandefinition.getscope();
//取得當前bean的范圍,也即在定義中的scope=”request”的部分。
scope scope = (scope) this.scopes.get(scopename);//得到bean工廠中的范圍處理器
if (scope == null) {
throw new illegalstateexception("no scope registered for scope '" + scopename + "'");
}
try {
//使用scope.get(beanname,objectfactory)從指定的范圍中得到或創(chuàng)建bean實例
object scopedinstance = scope.get(beanname, new objectfactory() {
public object getobject() throws beansexception {
beforeprototypecreation(beanname);//前攔截
try {
return createbean(beanname, mergedbeandefinition, args);
//調用子類的createbean實現(xiàn)真正的bean創(chuàng)建工作
}
finally {
afterprototypecreation(beanname);//后攔截
}
}
});
bean = getobjectforbeaninstance(scopedinstance, name, mergedbeandefinition);//返回正確類型的bean實例
}
catch (illegalstateexception ex) {
throw new beancreationexception(beanname, "scope '" + scopename + "' is not active", ex);
}
默認情況下,低層的bean工廠中只支持singleton及prototype兩種類型的bean。當把scope設置成request及session時將會出現(xiàn)不能正確識別scope的錯誤。這是因為普通的bean工廠都沒有注冊新的scope。只有在webapplicationcontext中注冊才注冊了新類型的bean。
下面看實現(xiàn)注冊scope的代碼:
在webapplicationcontext中定義常量
public interface webapplicationcontext extends applicationcontext {
string scope_request = "request";
string scope_session = "session";
string scope_global_session = "globalsession";
}
然后在所有類型的web應用上下文的實現(xiàn)中,都在bean工廠的攔載過程中通過postprocessbeanfactory方法來注冊新類型scope,如genericwebapplicationcontext、staticwebapplicationcontext、abstractrefreshablewebapplicationcontext等webapplication應用上下文實現(xiàn)中。
protected void postprocessbeanfactory(configurablelistablebeanfactory beanfactory) {
beanfactory.registerscope(scope_request, new requestscope());//注冊request類型的bean
beanfactory.registerscope(scope_session, new sessionscope(false));//注冊session類型的bean
beanfactory.registerscope(scope_global_session, new sessionscope(true));//注冊glogalsession 的bean
}
結合上面的代碼,現(xiàn)在應該明白為什么只有在web應用上下文中才能使用新增加三種類型的bean了吧。當然,由于有了scope,我們也可以非常輕松的實現(xiàn)我們自己的scope,增加新用戶自定義類型的bean,然后設計出一個適合我們自己的bean工廠。