0.先醒醒腦
1.關(guān)于scope
- singleton:在spring容器中只存在一個(gè)實(shí)例,所有對(duì)該對(duì)象的引用將共享這個(gè)實(shí)例,該實(shí)例從容器啟動(dòng),并因?yàn)榈谝淮伪徽?qǐng)求而初始化之后,將一直存活到容器退出;
- prototype:容器在接受到該類型對(duì)象的請(qǐng)求時(shí),會(huì)每次都重新生成一個(gè)新的對(duì)象實(shí)例給請(qǐng)求方,該對(duì)象的實(shí)例化以及屬性設(shè)置等工作都是由容器負(fù)責(zé)的,但是只要準(zhǔn)備完畢,并且對(duì)象實(shí)例返回給請(qǐng)求方的時(shí)候,容器就不再擁有當(dāng)前返回對(duì)象的引用,請(qǐng)求方需要自己負(fù)責(zé)當(dāng)前返回對(duì)象的生命周期管理工作,包括容器的摧毀;
- request:XmlWebApplicationContext會(huì)為每個(gè)HTTP請(qǐng)求創(chuàng)建一個(gè)全新的RequestProcessor對(duì)象供當(dāng)前請(qǐng)求使用贱迟,當(dāng)請(qǐng)求結(jié)束后兑燥,該對(duì)象實(shí)例的生命周期即告結(jié)束;從不是很?chē)?yán)格的意義上說(shuō)晰甚,request可以看作prototype的一種特例刻像,除了場(chǎng)景更加具體 之外穿香,語(yǔ)意上差不多;
- session:request相比,除了擁有session scope的bean的實(shí)例具有比request scope的bean可能更長(zhǎng)的存活時(shí)間绎速,其他方面真是沒(méi)什么差別。
- global session:沒(méi)啥好說(shuō)的;
2.自定義scope
要實(shí)現(xiàn)自己的scope焙蚓,可以參照RequestScope和SessionScope,首先必須實(shí)現(xiàn)Scope接口或者繼承AbstractRequestAttributesScope,接口定義中的4個(gè)方法并非都是必須的纹冤,但get和remove方法必須實(shí)現(xiàn);
1.有了Scope的實(shí)現(xiàn)類之后,我們需要把這個(gè)Scope注冊(cè)到容器中,才能供相應(yīng)的bean定義使用。使用編碼注冊(cè)的方式是通過(guò)ConfigurableBeanFactory#registerScope注冊(cè)自定義scope;
Scope customScope = new CustomScope();
beanFactory.registerScope("custom",customScope);
正常情況下都是按如下方式注冊(cè):
ClassPathXmlApplicationContext context = ...;
context.getBeanFactory().registerScope("custom", new CustomScope());
2.使用xml的方式注入:
<bean id="custom" class="CustomScope"/>
<bean id="customerScope" class="org.springframework.beans.factory.config.CustomScopeConfigurer">
<property name="scopes">
<map>
<entry key="custom">
<bean class="custom"/>
</entry>
</map>
</property>
</bean>
<bean id="usesScope" class="org.springframework.beans.TestBean" scope="custom"/>
原因是這樣:
CustomScopeConfigurer 實(shí)現(xiàn)了BeanFactoryPostProcessor,BeanClassLoaderAware等接口,SpringIoC容器允許BeanFactoryPostProcessor在容器實(shí)例化任何bean之前讀取bean的定義(配置元數(shù)據(jù))购公,并可以修改它萌京。而CustomScopeConfigurer中實(shí)現(xiàn)的postProcessBeanFactory方法;
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
if (this.scopes != null) {
Iterator var2 = this.scopes.entrySet().iterator();
while(var2.hasNext()) {
Entry<String, Object> entry = (Entry)var2.next();
String scopeKey = (String)entry.getKey();
Object value = entry.getValue();
if (value instanceof Scope) {
beanFactory.registerScope(scopeKey, (Scope)value);
} else {
Class scopeClass;
if (value instanceof Class) {
scopeClass = (Class)value;
Assert.isAssignable(Scope.class, scopeClass, "Invalid scope class");
beanFactory.registerScope(scopeKey, (Scope)BeanUtils.instantiateClass(scopeClass));
} else {
if (!(value instanceof String)) {
throw new IllegalArgumentException("Mapped value [" + value + "] for scope key [" + scopeKey + "] is not an instance of required type [" + Scope.class.getName() + "] or a corresponding Class or String value indicating a Scope implementation");
}
scopeClass = ClassUtils.resolveClassName((String)value, this.beanClassLoader);
Assert.isAssignable(Scope.class, scopeClass, "Invalid scope class");
beanFactory.registerScope(scopeKey, (Scope)BeanUtils.instantiateClass(scopeClass));
}
}
}
}
}
它同樣會(huì)去掃描加載的配置文件中的scope,并進(jìn)行注冊(cè);
補(bǔ)充:關(guān)于BeanFactoryPostProcessor的內(nèi)容,Spring IoC容器允許同時(shí)可以定義多個(gè)BeanFactoryPostProcessor,通過(guò)實(shí)現(xiàn)order接口來(lái)確定各個(gè)BeanFactoryPostProcessor執(zhí)行順序宏浩。注冊(cè)一個(gè)BeanFactoryPostProcessor實(shí)例需要定義一個(gè)Java類來(lái)實(shí)現(xiàn)BeanFactoryPostProcessor接口知残,并重寫(xiě)該接口的postProcessorBeanFactory方法。通過(guò)beanFactory可以獲取bean的定義信息比庄,并可以修改bean的定義信息求妹。
public interface BeanFactoryPostProcessor {
void postProcessBeanFactory(ConfigurableListableBeanFactory var1) throws BeansException;
}
在Spring中內(nèi)置了一些BeanFactoryPostProcessor實(shí)現(xiàn)類乏盐,可遵循如下關(guān)系延伸閱讀;
關(guān)于在spring-boot中自定義scope其實(shí)也類似制恍,改天再將案例貼出!