1 Scope作用通过@Scope注解可以指定Bean的作用域,默认情况都是单例的(
ConfigurableBeanFactory.SCOPE_SINGLETON=singleton)
在创建bean实例时就是根据当前定义BeanDefinition中的Scope来做不同的创建,源码如下:
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
// other code
} else {
// other code
try {
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
// other code
// Create bean instance.
// 根据BeanDefinition中定义的Scope创建实例
// 判断如果是单例
if (mbd.isSingleton()) {
// 如果是单例Bean会将Bean保存到缓存中singletonObjects
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
} catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
// 判断如果是原型(多例)
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
} finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
else {
String scopeName = mbd.getScope();
if (!StringUtils.hasLength(scopeName)) {
throw new IllegalStateException("No scope name defined for bean 麓" + beanName + "'");
}
Scope scope = this.scopes.get(scopeName);
// 当集合中也不存在时抛出异常
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, () -> {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
} finally {
afterPrototypeCreation(beanName);
}
});
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
} catch (IllegalStateException ex) {
throw new BeanCreationException(beanName, "Scope '" + scopeName + "' is not active for the current thread; consider " + "defining a scoped proxy for this bean if you intend to refer to it from a singleton", ex);
}
}
} catch (BeansException ex) {
cleanupAfterBeanCreationFAIlure(beanName);
throw ex;
}
}
// other code
return (T) bean;
}
从上面源码看到分别判断是了 是否是 Singleton及Proptotype,如果都不是则会从Map<String, Scope> scopes中获取 。如果当前你配置的@Scope不是singleton及prototype那么从scopes集合中取(这个集合是通过AbstractBeanFactory#registerScope方法进行注册的,一般我们可以通过
BeanDefinitionRegistryPostProcessor进行注册),如果集合中也不存在那么就会抛出异常 。如果存在就会执行Scope#get方法
Scope scope = this.scopes.get(scopeName);
Object scopedInstance = scope.get(beanName, () -> {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
} finally {
afterPrototypeCreation(beanName);
}
});
2 自定义Scope自定义Scope
public class CustomScope implements Scope {
private Object target ;
@Override
public Object get(String name, ObjectFactory<?> objectFactory) {
return target != null ? target : objectFactory.getObject() ;
}
// 如果调用了这个方法,那么下次在注入有@Scope("custom")的bean时 将会重写调用objectFactory.getObject()方法 。
@Override
public Object remove(String name) {
推荐阅读
- 如何在 SQL Server 中备份和恢复数据库
- 盘点蔬果中的“护肝大将”
- 欧洲发展中国家有哪些 发展中国家有哪些
- 面试中的2个雷区:避免触碰这些小事
- 五大必备面试技巧:在职场竞争中脱颖而出
- 四季茶花在北方家中适合养殖吗视频 四季茶花在北方家中适合养殖吗
- 男生中文名字简短好听 男生好听罕见的中文名字
- 一年中有7个大月,5个小月对吗 一年中有几个大月几个小月
- 福禄寿喜:文物中的中国吉祥文化
- 梦见肺有什么征兆