首页 > 编程语言 >从doCreateBean看java对象的实例化和初始化

从doCreateBean看java对象的实例化和初始化

时间:2022-12-03 16:32:12浏览次数:46  
标签:初始化 java mbd beanName BeanCreationException bean 实例 doCreateBean

下面是spring 6.0源码中doCreateBean的部分源码

  /**
* Actually create the specified bean. Pre-creation processing has already happened
* at this point, e.g. checking {@code postProcessBeforeInstantiation} callbacks.
* <p>Differentiates between default bean instantiation, use of a
* factory method, and autowiring a constructor.
*
* @param beanName the name of the bean
* @param mbd the merged bean definition for the bean
* @param args explicit arguments to use for constructor or factory method invocation
* @return a new instance of the bean
* @throws BeanCreationException if the bean could not be created
* @see #instantiateBean
* @see #instantiateUsingFactoryMethod
* @see #autowireConstructor
*/
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {

// Instantiate the bean.
// 这个BeanWrapper是用来持有创建出来的bean对象的
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
// 如果是单例对象,从factoryBean实例缓存中移除当前bean定义信息
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 根据执行bean使用对应的策略创建新的实例,如工厂方法,构造函数主动注入、简单初始化
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
// 得到半成品的对象,只完成了实例化,未实现初始化
Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}

// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {

applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);// 完成注解扫描,为后面的属性填充做准备
} catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}

// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
// 加入三级缓存,但加的不是对象,而是拉姆达表达式
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}

// Initialize the bean instance.
Object exposedObject = bean;
try {
// 对bean的属性进行填充,将各个属性值注入,其中,可能存在依赖于其他bean属性,则会递归初始化依赖的bean
populateBean(beanName, mbd, instanceWrapper);
//执行初始化逻辑
exposedObject = initializeBean(beanName, exposedObject, mbd);//aop
} catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
} else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}

……
}

透过源码,我们可以清晰的看到,是先执行createBeanInstance()实例化,再执行initializeBean,进行初始化操作

从doCreateBean看java对象的实例化和初始化_实例化


什么是实例化,实例化干了些啥

java的实例化就是在内存中为对象开辟了一个空间,并且在栈内存上生成一个引用,指向那片内存地址,这个过程就叫实例化,

此时对象内部的成员变量还都是默认值,如果是对象,默认为null,如果是int,默认为0

什么是初始化

初始化就是给实例化对象内的成员变量赋初始值,例如如下代码,实例化时只创建了A对象,但成员变量a的值还只是默认值0,而初始化就是将10赋值给成员变量a。

public class A{

private int a = 10;
}

其实要再深入一点,可以追究到类的加载过程,写在idea上的代码怎么就变成了一个个的bean对象了呢?我们来把它们细分为如下几个步骤

coding

利用CV大法,从StackOverFlow或者github上搞来一段足以改变世界的代码,粘贴在idea里面

  public static void main(String[] args) {
System.out.println("Hello world");
}

从doCreateBean看java对象的实例化和初始化_实例化_02

compiling

使用idea的自动编译功能,把.java文件编译为.class文件


从doCreateBean看java对象的实例化和初始化_初始化_03

然后启动void main函数,接下来就要发生神奇的事情了,控制台怎么就say hello了呢?其实这个过程分三步

Loding

首先就是jvm会将我们的class文件load进内存中,一个一个字节的读进内存。

Linking

读进内存之后,然后根据jvm的规范,逐个解析里面的字节,这个过程又分三个小步

verification

首先是校验环节,检查加载进来的字符是否符合jvm规范,比如是不是以coffee baby开头的,等等,如果不符合,直接就失败,停机给你看。

preparation

通过了校验环节,然后就是给class文件的静态变量赋默认值,不是赋初始值,比如 static int a = 1,在这个步骤,a先赋值为0。

resolution

然后就是把class文件中常量池里面的符号引用转换成内存地址。

Initializing

执行完Linking之后,才是初始化,这个时候才是给静态变量赋初始值。





标签:初始化,java,mbd,beanName,BeanCreationException,bean,实例,doCreateBean
From: https://blog.51cto.com/u_15696939/5908583

相关文章