目录
getSingleton(String beanName,ObjectFactory of)方法详解
前言:我们在上一篇博文 spring源码分析之bean的加载 中已经介绍了有关spring的bean加载过程中的主要流程,只是在创建不同scope范围的bean实例的过程中留下了伏笔,那么这边博文作者针对其上面博文有关手动创建bean实例进行详细的介绍。
一、不同scope实例创建的简单分析
先简单补充一下实例创建的代码
1、单例对象创建
逻辑代码:单例对象使用beanFactory的重载重载方法 getSingleton(String beanName,ObjectFactory of)。
ObejctFactory是一个接口式接口,这里使用了匿名内部类 调用createBean()方法 具体的创建bean实例的正式该方法。
//创建单例对象代码片段
sharedInstance = getSingleton(beanName, () -> {
try {
//具体的调用逻辑是调用ObjectFactory其匿名内部类的getObject()方法
//方法中createBean()方法
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
});
getSingleton(String beanName,ObjectFactory of)方法详解
/**
* 创建单例对象
* @param beanName 创建对象的beanName
* @param singletonFactory 具体调用该对象的getObject()方法创建对应的bean实例
* @return 返回创建的对象
*/
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
synchronized (this.singletonObjects) {
//从单例缓存中获取单例对象
Object singletonObject = this.singletonObjects.get(beanName);
//如果对象为null
if (singletonObject == null) {
//则进行单例对象的创建操作
//判断如果该beanFactory被销毁则抛出异常
if (this.singletonsCurrentlyInDestruction) {
throw new BeanCreationNotAllowedException();
}
if (logger.isDebugEnabled()) {
logger.debug("Creating shared instance of singleton bean beanName);
}
//单例对象创建之前的回调 默认实现是将其添加到正在创建的列表中
//表明该对象正在被创建 单例对象 防止多次创建
beforeSingletonCreation(beanName);
boolean newSingleton = false;
//创建保存异常的信息 用于存储创建实例对象的异常信息
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
//调用ObjectFactory 创建实例对象
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
catch (IllegalStateException ex) {
//在创建对象的时候出现异常 可能从别的途径隐式的创建对象 所有从缓存中获取
// 看看是否有了,破罐子破摔
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw ex;
}
}
catch (BeanCreationException ex) {
//添加创建bean实例异常的信息
if (recordSuppressedExceptions) {
for (Exception suppressedException : this.suppressedExceptions) {
ex.addRelatedCause(suppressedException);
}
}
throw ex;
}
finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
//单例对象创建之前的回调 默认实现将正在创建的该bean标识
//从正在创建bean的列表中移除
afterSingletonCreation(beanName);
}
if (newSingleton) {
//添加新创建的单例对象到缓存中
addSingleton(beanName, singletonObject);
}
}
//返回创建的单例对象
return singletonObject;
}
2、原型对象创建
创建原型对象的核心逻辑和单例创建实例一致调用createBean()方法
//原型对象创建的代码逻辑
Object prototypeInstance = null;
try {
//原型对象创建之前的回调
//主要功能是将创建的beanName 放入prototypesCurrentlyInCreation中
beforePrototypeCreation(beanName);
//创建原型对象的方式和创建单例对象的一样 这里不再详述
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
//原型对象创建之前的回调
//主要功能是将创建的beanName从prototypesCurrentlyInCreation移除
afterPrototypeCreation(beanName);
}
3、其他Scope范围bean实例创建
调用scope的get(String beanName,ObjectFactory of), get()方法中调用ObjectFactory的getObject() 创建对象实例,最终调用和上面的创建bean实例流程一致调用creatBean()方法
//调用scope的get方法,具体的创建的操作是在其第二个匿名参数ObjectFactory
//里面也是调用createBean()
Object scopedInstance = scope.get(beanName, () -> {
//与原型对象创建之前的回调一致
//标记该beanName对应的bean实例对象正在被创建
beforePrototypeCreation(beanName);
try {
//具体创建bean实例的核心代码
return createBean(beanName, mbd, args);
}
finally {
//与原型对象创建之后的回调一致
//移除beanName对应的bean实例从标记中
afterPrototypeCreation(beanName);
}
});
//scope 获取对象的
public Object get(String name, ObjectFactory<?> objectFactory) {
//先从缓存中获取对应的bean实例 如果没有则调用ObjectFactory的getObject()方法
//getObject()方法中的实现是上面匿名内部类的createBean()方法
Map<String, Object> scope = (Map)this.threadScope.get();
Object scopedObject = scope.get(name);
if (scopedObject == null) {
scopedObject = objectFactory.getObject();
scope.put(name, scopedObject);
}
return scopedObject;
}
对于上面三种类型bean实例创建,各有不同点,但是最终都是调用相同的createBean()来进行实例的创建。下面我们来分析三种创建bean实例的核心代码createBean()方法。
二、创建bean实例的核心流程分析
1、creatBean()方法
//根据RootBeanDefinition 创建对应的bean实例
protected Object createBean(String beanName, RootBeanDefinition mbd,
@Nullable Object[] args) throws BeanCreationException {
if (logger.isDebugEnabled()) {
logger.debug("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
//1、解析beanDefinition中获取其中的class属性
//如果beanDefinition中没有填充class属性
//填充对应的RootBeanDefinition 的BeanClass
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass()
&& mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// Prepare method overrides.
try {
//2、在beans.xml 中replace-method、lookup 配置
//会被解析到BeanDefinition的MethodOverride中
//标记BeanDefintion中的某些MethodOverride 只有一个方法 标明该方法没有重载方法
//在进行methodOverrides实例化的时候避免参数检查的开销
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(ex);
}
try {
//3、通过应用bean的后置处理器 返回一个代理对象而非目标对象,
//此处是我们常用的AOP功能的实现
//这里有一个短路操作 如果代理对象存在则直接返回代理对象 不在做后续的操作
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(ex);
}
try {
//4、对于普通的bean 实例执行真正的创建bean实例的逻辑
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isDebugEnabled()) {
logger.debug("Finished creating instance of bean '" + beanName + "'");
}
//返回bean实例对象
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex)
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(ex);
}
}
上面代码的主要逻辑如下:
- 解析beanDefinition中获取其中的class属性,如果beanDefinition中没有填充class属性,填充对应的RootBeanDefinition的class属性。
- 在beans.xml 中replace-method、lookup 配置 会被解析到BeanDefinition的MethodOverride中,bean实例化的时候如果检测道存在MethodOverride属性,会动态的为当前bean生成代理并使用对应的拦截器为bean做增强处理。同时标记如果BeanDefintion中的某些MethodOverride只有一个方法标明该方法没有重载方法,避免参数检查的开销。
-
public void prepareMethodOverrides() throws BeanDefinitionValidationException { //判断beanDefintion是否有MethodOverrides if (hasMethodOverrides()) { getMethodOverrides().getOverrides().forEach(this::prepareMethodOverride); } } protected void prepareMethodOverride(MethodOverride mo) throws BeanDefinitionValidationException { //获取class中 方法名对应的重载方法的个数 int count = ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName()); if (count == 0) { throw new BeanDefinitionValidationException(); } //如果重载方法个数为1 则说明该方法没有重载方法 设置MethodOverride 的重载标识为false else if (count == 1) { // Mark override as not overloaded, to avoid the overhead of arg type checking. mo.setOverloaded(false); } }
- 通过应用bean的后置处理器 返回一个代理对象而非目标对象,此处是我们常用的AOP功能的实现。这里有一个短路操作 如果代理对象存在则直接返回代理对象不在做后续的操作。
-
//应用后置处理器,对bean实例进行代理增强 我们的AOP代理增强也是在该处来进行实现 @Nullable protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) { Object bean = null; if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) { if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { //获取bean的class实例 Class<?> targetType = determineTargetType(beanName, mbd); if (targetType !&