在 Spring 中存在着不同的 scope,默认是 singleton,还有prototype等。下面便分析各个scope。
1.singleton。
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
//获取singletonObjects全局锁
synchronized (this.singletonObjects) {
//获取singletonObjects对应的bean实例
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
if (this.singletonsCurrentlyInDestruction) {
throw new BeanCreationNotAllowedException(beanName,
"Singleton bean creation not allowed while singletons of this factory are in destruction " +
"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
}
if (logger.isDebugEnabled()) {
logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
}
//创建bean之前的处理,添加singletonsCurrentlyInCreation缓存
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
//初始化bean 其实就是调用createBean()
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
catch (IllegalStateException ex) {
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw ex;
}
}
catch (BeanCreationException ex) {
if (recordSuppressedExceptions) {
for (Exception suppressedException : this.suppressedExceptions) {
ex.addRelatedCause(suppressedException);
}
}
throw ex;
}
finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
//后置处理,singletonsCurrentlyInCreation除去缓存
afterSingletonCreation(beanName);
}
//添加进入对应的缓存中,刷新对应缓存
if (newSingleton) {
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
在isSingleton为true情况下,getSingleton()和createBean()方法。
分析getSingleton,这个方法并不是核心区创建bean的函数,而是对创建前后进行逻辑操作和校验。
- 获取singletonObjects全局锁,并获取对应的bean实例,如果bean存在直接返回。这样可以确保单例模式只存在唯一的 bean实例
- 如果不存在,进行beforeSingletonCreation(beanName),singletonsCurrentlyInCreation加入缓存
-
singletonFactory.getObject()调用createBean()创建bean
- afterSingletonCreation去除singletonsCurrentlyInCreation缓存
- addSingleton()添加刷新对应的缓存。
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
this.singletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
一个 put、一个 add、两个 remove。singletonObjects 单例 bean 的缓存,singletonFactories 单例 beanFactory 的缓存,earlySingletonObjects “早期”创建的单例 bean 的缓存,registeredSingletons 已经注册的单例缓存。
原型模式:
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
原型模式的创建也是一样的:
- 调用
beforeSingletonCreation()
记录加载原型模式 bean 之前的加载状态,即前置处理。 - 调用
createBean()
创建一个 bean 实例对象。 - 调用
afterSingletonCreation()
进行加载原型模式 bean 后的后置处理。 - 调用
getObjectForBeanInstance()
从 bean 实例中获取对象。
其他:
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);
}
三个模块最主要的两个方法createBean()和getObjectForBeanInstance()。createBean()下篇会讲解。getObjectForBeanInstance()是这样解释的(《Spring 源码深度解析》):
这个方法主要是验证以下我们得到的 bean 的正确性,其实就是检测当前 bean 是否是 FactoryBean 类型的 bean,如果是,那么需要调用该 bean 对应的 FactoryBean 实例的 getObject()
作为返回值。无论是从缓存中获得到的 bean 还是通过不同的 scope 策略加载的 bean 都只是最原始的 bean 状态,并不一定就是我们最终想要的 bean。举个例子,加入我们需要对工厂 bean 进行处理,那么这里得到的其实是工厂 bean 的初始状态,但是我们真正需要的是工厂 bean 中定义 factory-method 方法中返回的 bean,而 getObjectForBeanInstance()
就是完成这个工作的。