Spring中Bean的作用域Scope你知道多少?如何自定义作用域?

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 codetry {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保存到缓存中singletonObjectssharedInstance = 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 codereturn (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 ;@Overridepublic Object get(String name, ObjectFactory<?> objectFactory) {return target != null ? target : objectFactory.getObject() ;}// 如果调用了这个方法,那么下次在注入有@Scope("custom")的bean时 将会重写调用objectFactory.getObject()方法 。@Overridepublic Object remove(String name) {


推荐阅读