你不必害怕沉沦堕落,只消你能不断的自拔与更新
Spring IoC之获取Bean
非单例Bean的获取
Spring Bean获取的主体代码在AbstractBeanFactory的doGetBean方法中,看下面的方法:
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
// 转换BeanName,如果name参数传过来是aliasName的话,在这里会根据aliasName取出真正的BeanName
final String beanName = transformedBeanName(name);
Object bean;
// 首先检查单例缓存里面有没有这个Bean
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 + "'");
}
}
// 将取出的object(可能是一个FactoryBean)转换成Bean的类型
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// 检查是否已经在创建中,如果正在创建中,就确定存在循环引用
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// 检查ParentBeanFactory是否存在Bean定义信息
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// 如果ParentBeanFacotory不为空而且此BeanFactory不包含Bean定义信息
String nameToLookup = originalBeanName(name);
if (args != null) {
// 如果参数不为空,带上参数将获取Bean委托给ParentBeanFactory
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
// 如果参数为空,则将获取Bean委托给ParentBeanFactory的标准getBean方法
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
// typeCheckOnly,实例用来做类型检测的,而不是真正地拿来用的
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
// 如果Bean的定义信息在子Bean定义信息中,则合并到当前的Bean定义信息中
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// 处理depends on的情况,确保当前Bean依赖的Bean先创建
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dependsOnBean : dependsOn) {
getBean(dependsOnBean);
registerDependentBean(dependsOnBean, beanName);
}
}
// 开始创建Bean实例
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory() {
public Object getObject() throws BeansException {
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);
}
elseif (mbd.isPrototype()) {
// Bean的Scope是Prototype,创建一个新实例
Object prototypeInstance = null;
try {
// 在Bean创建之前,默认行为是:将当前Bean标记为正在创建中,用于前面检测循环引用
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
// 在Bean创建之后,默认行为是:将当前Bean标记为不在创建中,用于前面检测循环引用
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 '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, new ObjectFactory() {
public Object getObject() throws BeansException {
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);
}
}
}
// 检测Bean实例和需要的类型是否匹配
if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
return (T) bean;
}
从这里可以看出,Spring是首先尝试从单例缓存中获取Bean,如果找不到,然后在根据不同的Bean Scope调用不同的方法去创建Bean。