在 Spring 中存在着不一样的 scope,默认是 singleton ,还有 prototype、request 等等其余的 scope ,接下来咱们分析一下它们的建立过程。java
Spring 的 scope 默认为 singleton,其初始化的代码以下: web
if (mbd.isSingleton()) {
sharedInstance = this.getSingleton(beanName, () -> {
try {
return this.createBean(beanName, mbd, args);
} catch (BeansException var5) {
this.destroySingleton(beanName);
throw var5;
}
});
bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
复制代码
第一部分分析了从缓存中获取单例模式的 bean,可是若是缓存中不存在呢?则须要从头开始加载 bean,这个过程由 getSingleton(beanName, singletonFactory)
实现。 spring
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
// 全局加锁
synchronized(this.singletonObjects) {
// 从缓存中检查一遍
// 由于 singleton 模式其实就是复用已经建立的 bean 因此这步骤必须检查
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
....
// 加载前置处理
this.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 var16) {
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw var16;
}
} catch (BeanCreationException var17) {
....
} finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
// 后置处理
this.afterSingletonCreation(beanName);
}
// 加入缓存中
if (newSingleton) {
this.addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
复制代码
其实这个过程并无真正建立 bean,仅仅只是作了一部分准备和预处理步骤,真正获取单例 bean 的方法实际上是由 singletonFactory.getObject()
这部分实现,而 singletonFactory 由回调方法产生。那么这个方法作了哪些准备呢?缓存
再次检查缓存是否已经加载过,若是已经加载了则直接返回,不然开始加载过程。app
调用 beforeSingletonCreation()
记录加载单例 bean 以前的加载状态,即前置处理。ide
调用参数传递的 ObjectFactory 的 getObject()
实例化 bean。函数
调用 afterSingletonCreation()
进行加载单例后的后置处理。post
将结果记录并加入值缓存中,同时删除加载 bean 过程当中所记录的一些辅助状态。测试
这里咱们看一下 addSingleton()
方法this
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);
}
}
复制代码
结合循环依赖章节中所讲,这一步就是清除二级和三级缓存中的数据,添加到一级缓存中,位于一级缓存中的单例数据能够屡次被调用。
接着来重点关注 AbstractAutowireCapableBeanFactory 类中实现的 createBean()方法,其定义以下:
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
if (this.logger.isTraceEnabled()) {
this.logger.trace("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
// 确保此时的 bean 已经被解析了
Class<?> resolvedClass = this.resolveBeanClass(mbd, beanName, new Class[0]);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
// 若是获取的class 属性不为null,则克隆该 BeanDefinition
// 主要是由于该动态解析的 class 没法保存到到共享的 BeanDefinition
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
try {
// 验证和准备覆盖方法
mbdToUse.prepareMethodOverrides();
} catch (BeanDefinitionValidationException var9) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(), beanName, "Validation of method overrides failed", var9);
}
Object beanInstance;
try {
// 给 BeanPostProcessors 一个机会用来返回一个代理类而不是真正的类实例
// AOP 的功能就是基于这个地方
beanInstance = this.resolveBeforeInstantiation(beanName, mbdToUse);
if (beanInstance != null) {
return beanInstance;
}
} catch (Throwable var10) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", var10);
}
try {
// 执行真正建立 bean 的过程
beanInstance = this.doCreateBean(beanName, mbdToUse, args);
if (this.logger.isTraceEnabled()) {
this.logger.trace("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
} catch (ImplicitlyAppearedSingletonException | BeanCreationException var7) {
throw var7;
} catch (Throwable var8) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", var8);
}
}
复制代码
主要过程以下:
prepareMethodOverrides()
方法涉及到 BeanDefinition,后续会作介绍。
resolveBeforeInstantiation()
的做用是给 BeanPostProcessors 后置处理器返回一个代理对象的机会,其实在调用该方法以前 Spring 一直都没有建立 bean ,那么这里返回一个 bean 的代理类有什么做用呢?做用体如今后面的 if
判断:
if (beanInstance != null) {
return beanInstance;
}
复制代码
若是代理对象不为空,则直接返回代理对象,这一步骤有很是重要的做用,Spring 后续实现 AOP 就是基于这个地方判断的。
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
复制代码
这个方法核心就在于 applyBeanPostProcessorsBeforeInstantiation()
和 applyBeanPostProcessorsAfterInitialization()
两个方法,before 为实例化前的后处理器应用,after 为实例化后的后处理器应用。最终仍是由 BeanPostProcessor 接口实现类来完成相应的工做。
接下来就该最核心的建立 bean 的工做,该过程有 doCreateBean()
实现,以下:
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
// BeanWrapper是对Bean的包装,其接口中所定义的功能很简单包括设置获取被包装的对象,获取被包装bean的属性描述器
BeanWrapper instanceWrapper = null;
// 单例模型,则从未完成的 FactoryBean 缓存中删除
if (mbd.isSingleton()) {
instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
}
// 使用合适的实例化策略来建立新的实例:工厂方法、构造函数自动注入、简单初始化
if (instanceWrapper == null) {
instanceWrapper = this.createBeanInstance(beanName, mbd, args);
}
// 包装的实例对象
Object bean = instanceWrapper.getWrappedInstance();
// 包装的实例对象的类型
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// 检测是否有后置处理
// 若是有后置处理,则容许后置处理修改 BeanDefinition
synchronized(mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
this.applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
} catch (Throwable var17) {
....
}
mbd.postProcessed = true;
}
}
// 解决单例模式的循环依赖
// 单例模式 & 运行循环依赖&当前单例 bean 是否正在被建立
boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName);
if (earlySingletonExposure) {
if (this.logger.isTraceEnabled()) {
this.logger.trace("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references");
}
this.addSingletonFactory(beanName, () -> {
return this.getEarlyBeanReference(beanName, mbd, bean);
});
}
Object exposedObject = bean;
try {
// 对 bean 进行填充,将各个属性值注入,其中,可能存在依赖于其余 bean 的属性
// 则会递归初始依赖 bean
this.populateBean(beanName, mbd, instanceWrapper);
// 调用初始化方法
exposedObject = this.initializeBean(beanName, exposedObject, mbd);
} catch (Throwable var18) {
if (var18 instanceof BeanCreationException && beanName.equals(((BeanCreationException)var18).getBeanName())) {
throw (BeanCreationException)var18;
}
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", var18);
}
/**
* 循环依赖处理
*/
if (earlySingletonExposure) {
// 获取 earlySingletonReference
Object earlySingletonReference = this.getSingleton(beanName, false);
// 只有在存在循环依赖的状况下,earlySingletonReference 才不会为空
if (earlySingletonReference != null) {
// 若是 exposedObject 没有在initializeBean初始化方法中被改变,也就是没有被加强
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
} else if (!this.allowRawInjectionDespiteWrapping && this.hasDependentBean(beanName)) {
String[] dependentBeans = this.getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet(dependentBeans.length);
String[] var12 = dependentBeans;
int var13 = dependentBeans.length;
for(int var14 = 0; var14 < var13; ++var14) {
String dependentBean = var12[var14];
if (!this.removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
....
}
}
}
}
try {
// 注册 bean
this.registerDisposableBeanIfNecessary(beanName, bean, mbd);
return exposedObject;
} catch (BeanDefinitionValidationException var16) {
.....
}
}
复制代码
总体的思路:
createBeanInstance()
实例化 bean,主要是将 BeanDefinition 转换为 BeanWrappercreateBeanInstance()
实例化 bean,赋零值populateBean()
属性填充initializeBean()
初始化 bean,包括前置、后置处理器的调用建立完 bean 实例后,还会执行 getObjectForBeanInstance()
方法,这个方法在缓存中获取单例 bean 一节有介绍到。
else if (mbd.isPrototype()) {
var11 = null;
Object prototypeInstance;
try {
this.beforePrototypeCreation(beanName);
prototypeInstance = this.createBean(beanName, mbd, args);
} finally {
this.afterPrototypeCreation(beanName);
}
bean = this.getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
复制代码
原型模式的初始化过程很简单:直接建立一个新的实例就能够了。过程以下:
beforeSingletonCreation()
记录加载原型模式 bean 以前的加载状态,即前置处理。createBean()
建立一个 bean 实例对象。afterSingletonCreation()
进行加载原型模式 bean 后的后置处理。getObjectForBeanInstance()
从 bean 实例中获取对象。原型模式下,执行 createBean()
相对来讲简单一些,这里就很少作介绍了。不过关于循环依赖队列中存在原型模式的 bean,须要注意一下,这里咱们仍是拿以前的案例来进行测试,作一下修改。
修改 beans.xml 文件,将其中的一个 bean 定义为原型模式:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="car" class="com.msdn.bean.AbstractCar" p:brand="宝马" p:money-ref="money" />
<bean id="person" class="com.msdn.bean.Person" p:name="herish" p:car-ref="car" />
<bean id="money" class="com.msdn.bean.Money" p:classification="工资" p:person-ref="person" scope="prototype"/>
</beans>
复制代码
新的测试代码:
@Test
public void cycleRely(){
ClassPathResource resource = new ClassPathResource("config/beans.xml");
BeanFactory beanFactory = new XmlBeanFactory(resource);
Person person = (Person) beanFactory.getBean("person");
System.out.println(person);
Money money = (Money) beanFactory.getBean("money");
Money money2 = (Money) beanFactory.getBean("money");
System.out.println(money == money2);
AbstractCar car = (AbstractCar) beanFactory.getBean("car");
AbstractCar car2 = (AbstractCar) beanFactory.getBean("car");
System.out.println(car == car2);
}
复制代码
运行结果为:
Person{name='herish', 拥有一辆car=AbstractCar{brand='宝马', money=Money{classification='工资', person=herish}}}
false
true
复制代码
从结果来看,貌似没什么问题,money 对象确实也再也不是单例,循环依赖也处理成功了。接下来咱们作一下修改:
@Test
public void cycleRely(){
ClassPathResource resource = new ClassPathResource("config/beans.xml");
BeanFactory beanFactory = new XmlBeanFactory(resource);
// Person person = (Person) beanFactory.getBean("person");
// System.out.println(person);
Money money = (Money) beanFactory.getBean("money");
Money money2 = (Money) beanFactory.getBean("money");
System.out.println(money == money2);
AbstractCar car = (AbstractCar) beanFactory.getBean("car");
AbstractCar car2 = (AbstractCar) beanFactory.getBean("car");
System.out.println(car == car2);
}
复制代码
运行该代码会报错:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'money' defined in class path resource [config/beans.xml]: Cannot resolve reference to bean 'person' while setting bean property 'person'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'person' defined in class path resource [config/beans.xml]: Cannot resolve reference to bean 'car' while setting bean property 'car'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'car' defined in class path resource [config/beans.xml]: Cannot resolve reference to bean 'money' while setting bean property 'money'; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'money': Requested bean is currently in creation: Is there an unresolvable circular reference?
复制代码
调试该代码能够发现问题,因为mbd.isSingleton()
(此处mbd为money对应的bean)为false,致使没有将相应的数据加入到三级缓存中,再次调用 getSingleton(beanName, allowEarlyReference)
方法返回结果为 null,致使进行到 isPrototypeCurrentlyInCreation(beanName)
方法时抛出异常。
String scopeName = mbd.getScope();
Scope 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, () -> {
this.beforePrototypeCreation(beanName);
Object var4;
try {
var4 = this.createBean(beanName, mbd, args);
} finally {
this.afterPrototypeCreation(beanName);
}
return var4;
});
bean = this.getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
} catch (IllegalStateException var23) {
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", var23);
}
复制代码
核心流程和原型模式同样,只不过获取 bean 实例是由 scope.get()
实现,以下:
public Object get(String name, ObjectFactory<?> objectFactory) {
// 获取 scope 缓存
Map<String, Object> scope = this.threadScope.get();
Object scopedObject = scope.get(name);
if (scopedObject == null) {
scopedObject = objectFactory.getObject();
// 加入缓存
scope.put(name, scopedObject);
}
return scopedObject;
}
复制代码
AbstractBeanFactory 类中对于 getBean(name)
方法的讲解终于结束了,这也是 bean 加载的过程。