从源码中理解bean作用域

#从源码中理解bean作用域
在这里插入图片描述

下面重点理解singleton、prototyp作用域,request、session和global-session类作用域不包括,需要在Spring MVC中理解

1.AbstractBeanFactory类中doGetBean方法
在这里插入图片描述

// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
	if (logger.isDebugEnabled()) {
		if (isSingletonCurrentlyInCreation(beanName)) {
			logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
					"' that is not fully initialized yet - a consequence of a circular reference");
		}
		else {
			logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
		}
	}
	bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}

从getSingleton方法获取一个单例bean

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
	Object singletonObject = this.singletonObjects.get(beanName);
	if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
		synchronized (this.singletonObjects) {
			singletonObject = this.earlySingletonObjects.get(beanName);
			if (singletonObject == null && allowEarlyReference) {
				ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
				if (singletonFactory != null) {
					singletonObject = singletonFactory.getObject();
					this.earlySingletonObjects.put(beanName, singletonObject);
					this.singletonFactories.remove(beanName);
				}
			}
		}
	}
	return singletonObject;
}

可以看出如果是作用域是Singleton的,是可以直接在缓存中到获取到bean返回,这个方法getSingleton就是常说三级缓存。

继续看下面doGetBean方法中的代码,重点是try,catch里面的代码会直接看到为什么,Singleton作用域的时候会返回同一个实例,而当作用域是prototype的时候每次回返回一个新的示例。

try {
	//获取bean的定义类型,是Singleton的,还是prototype,还是其他的
	final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
	checkMergedBeanDefinition(mbd, beanName, args);

	// Guarantee initialization of beans that the current bean depends on.
	String[] dependsOn = mbd.getDependsOn();
	if (dependsOn != null) {
		for (String dep : dependsOn) {
			if (isDependent(beanName, dep)) {
				throw new BeanCreationException(mbd.getResourceDescription(), beanName,
						"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
			}
			registerDependentBean(dep, beanName);
			try {
				getBean(dep);
			}
			catch (NoSuchBeanDefinitionException ex) {
				throw new BeanCreationException(mbd.getResourceDescription(), beanName,
						"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
			}
		}
	}

	// Create bean instance.
	//如果是单例的且从上面Object sharedInstance = getSingleton(beanName);拿不到那就说明没有,需要直接创建一个,并且要放到三级缓存中
	//(注意上面的Object sharedInstance = getSingleton(beanName);方法和下面这个方法不是同一个,参数不同,是重载方法。
	//上面那个getSingleton(beanName)方法是直接获取缓存中bean,下面这个getSingleton方法需要处理一些存、取到三级缓存的逻辑,不是同一个方法)
	if (mbd.isSingleton()) {
		sharedInstance = getSingleton(beanName, () -> {
			try {
				return createBean(beanName, mbd, args);
			}
			catch (BeansException ex) {
				// Explicitly remove instance from singleton cache: It might have been put there
				// eagerly by the creation process, to allow for circular reference resolution.
				// Also remove any beans that received a temporary reference to the bean.
				destroySingleton(beanName);
				throw ex;
			}
		});
		bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
	}
	//如果是原型prototype的,那就每次都会createBean一个新的实例
	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();
		final 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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值