Ioc容器中的依赖注入-中篇 createBean方法
程序员文章站
2022-05-07 18:37:15
...
前面已经介绍了 getBean方法,我们已经知道了getBean方法是依赖注入的起点,之后就会调用createBean方法
简单的描述下:createBean方法中的一些作用,Bean会根据BeanDefinition定义的要求生成,具体的实现类就是在AbstractAutowireCapableBeanFactory类中实现了createBean方法,在CreateBean方法中不但生成了需要的Bean,还对Bean的初始化做了一些处理,例如对BeanDefinition中的init-method属性定义,对Bean的后置处理器等
首先来看下依赖注入的整体流程图:
下面主要的就是对createBean方法进行具体的源码分析:
//这个方法是创建了一个Object类
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;
Class<?> resolvedClass = this.resolveBeanClass(mbd, beanName, new Class[0]);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
//判断这个类是否可以被实例化,通过类加载器来完成,可以的话就执行实例化
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 {
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);
}
}
接下来就是分析doCreateBean方法创建Bean对象的源码分析-也就是实际生成Bean的地方
doCreateBean()方法的分析
//记住这个抛出的异常都是BeanCreationException异常
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
//其中的BeanWrapper对象使用封装创建的bean的对象
BeanWrapper instanceWrapper = null;
//判断是否为单例模式的对象。是的就根据Bean名字删除缓存中的已经存在的bean
if (mbd.isSingleton()) {
instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
//在这里就是根据BeanName,RootBeanDefinition,Object数组来创建
instanceWrapper = this.createBeanInstance(beanName, mbd, args);
}
Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
//这里是对后置处理器执行加锁的操作
synchronized(mbd.postProcessingLock) {
//如果有后置处理器就是执行下面的代码
if (!mbd.postProcessed) {
try {
this.applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
} catch (Throwable var17) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", var17);
}
//设置后置处理器为true的状态
mbd.postProcessed = true;
}
}
//
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");
}
//将beanName添加进去SingletonFactory工厂里面去
this.addSingletonFactory(beanName, () -> {
return this.getEarlyBeanReference(beanName, mbd, bean);
});
}
//expose暴露的,无遮挡的对象
Object exposedObject = bean;
try {
//populate平民的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) {
Object earlySingletonReference = this.getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
} else if (!this.allowRawInjectionDespiteWrapping && this.hasDependentBean(beanName)) {
//这里进行了对BeanName的所有的依赖对象的代码分析
String[] dependentBeans = this.getDependentBeans(beanName);
//定义一个LinkedHashsset集合来存储
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()) {
throw new BeanCurrentlyInCreationException(beanName, "Bean with name '" + beanName + "' has been injected into other beans [" + StringUtils.collectionToCommaDelimitedString(actualDependentBeans) + "] in its raw version as part of a circular reference, but has eventually been wrapped. This means that said other beans do not use the final version of the bean. This is often the result of over-eager type matching - consider using 'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
try {
this.registerDisposableBeanIfNecessary(beanName, bean, mbd);
return exposedObject;
} catch (BeanDefinitionValidationException var16) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", var16);
}
}
其中主要的两个方法就是:
createBeanInstance 生成bean对象的方法
populateBean 这个方法,后面会进行详细的分析
上一篇: MYSQL学习与数据库综合实验(六)——实体完整性实验
下一篇: 十个Python程序员易犯的错误
推荐阅读
-
PHP中的服务容器与依赖注入的思想
-
PHP 在Swoole中使用双IoC容器实现无污染的依赖注入
-
Spring—IOC容器中Bean的生命周期方法
-
在Spring IoC中,依赖注入和依赖查找的数据来源一样吗?
-
.Net Core依赖注入中TryAddEnumerable 和TryAddTransient方法的区别
-
.NET Core中依赖注入AutoMapper的方法示例
-
Spring IOC DI依赖注入 IOC容器 Spring Bean的声明周期
-
详解C#中的依赖注入和IoC容器
-
ASP.NET Core Web 应用程序系列(一)- 使用ASP.NET Core内置的IoC容器DI进行批量依赖注入(MVC当中应用)
-
浅谈Spring IoC容器的依赖注入原理