接着上一篇,咱们继续doCreateBean方法的分析,doCreateBean内容比较多,我们这次主要是把它的整体流程说下,后续会逐个来分析每一个关键点。代码如下:
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
//关键点一
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final 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;
}
}
//关键点三
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)); // AService
}
Object exposedObject = bean;
try {
//关键点四
populateBean(beanName, mbd, instanceWrapper); //
//关键点五
exposedObject = initializeBean(beanName, exposedObject, mbd);
}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);
}
}
//关键点六
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!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 {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
关键点一
首次获取单例classA对象(续接“Spring框架系列之bean的生命周期底层原理07”的例子)肯定为空,这里会调用createBeanInstance实例化对象,何为实例化不用我多说了吧?就是new一个对象,既然是new一个对象,那如果ClassA这个类有多个构造函数咋办?Spring怎么知道调用哪个构造函数呢?所以这里Spring肯定需要有一个过程,用以推断具体的构造函数,这块我们放下一篇来详细展开。这里朋友们只要知道createBeanInstance方法就是通过new来得到一个对象,当然这里Spring是返回一个BeanWrapper类型的包装对象,对原始对象进行了封装。
关键点二
对象创建了以后,按照我们正常的java开发流程该做什么事情呢?是不是应该给对象的相关属性进行赋值了?Spring也是这么做的,但是Spring要明确知道,哪些属性是需要赋值的,这些属性赋值的方式是啥?是方法赋值还是属性赋值?
在Spring中有两个常见的注解是用来指定哪些属性是需要被赋值的,如Autowired、Value,当然还包括Inject,另外还有Resource等。在创建完成对象后,会调用
applyMergedBeanDefinitionPostProcessors方法来查找注入点,这些注入点就是被Autowired、Value、Resource这些注解标识的属性或者方法,具体怎么找的,我们放到后续篇幅详细分析,这里我们只需要知道通过applyMergedBeanDefinitionPostProcessors方法就能够找到具体的注入点,Spring将基于这些注入点进行赋值操作。
关键点三
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
如上代码段,标识如果当前创建的是单例bean,并且允许循环依赖,并且还在创建过程中,那么则需要提早暴露,默认情况下allowCircularReferences是为true的,也就是说Spring默认情况下是允许循环依赖的,什么是循环依赖?就是就是我们的案例,ClassA依赖ClassB,ClassB又依赖ClassA。而且当前beanName实例肯定是在创建中的,所以这里earlySingletonExposure的值是true,于是Spring调用addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)),注意这里的第二个参数是一个lambda表达式,addSingletonFactory方法代码如下:
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(singletonFactory, "Singleton factory must not be null");
synchronized (this.singletonObjects) {
if (!this.singletonObjects.containsKey(beanName)) {
this.singletonFactories.put(beanName, singletonFactory);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
}
该方法将lambda表达式添加到singletonFactories集合中,lambda表达式的执行代码如下:
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
}
}
}
return exposedObject;
}
会执行SmartInstantiationAwareBeanPostProcessor后置处理器的getEarlyBeanReference方法,大部分情况下getEarlyBeanReference返回的是原bean对象,除非AOP处理的情况下,这块我们后续讲AOP的时候详细分析。
关键点四
在找到注入点后,Spring接下来就是调用populateBean方法给属性赋值了,比如classA,需要给属性ClassB实例对象赋值,既然要赋值,那咱首先得有这个ClassB的实例对吧?但是此时Spring里面还没有ClassB这个类型的对象,所以在populateBean方法中又会进入ClassB对象的生命周期,来想下,当创建完ClassB的实例对象,也需要给ClassB对象的属性,也就是classA赋值,但是此时classA还不是一个健全的对象,于是出现了循环依赖问题,那Spring如何解决这个问题的呢?比较复杂,咱们后续会有专门篇幅分析。
关键点五
属性赋值完成后,调用initializeBean完成对象的初始化,以前笔者不是很明白初始化和实例化到底有啥区别,现在看来其实很简单,实例化就是JVM创建一个对象,而初始化则是需要结合实际的业务来看,更多的是业务层面的初始化操作。这里initializeBean方法其实执行了很多操作,比如执行Aware、初始化之前、初始化、初始化之后,具体我们后续篇幅分析。
关键点六
exposedObject = initializeBean(beanName, exposedObject, mbd),因为initializeBean方法中调用了后置处理器进行了处理,所以通过这个方法得到的exposedObject有可能已经被咱们自己增加的后置处理器修改了,如果咱们自己修改了,Spring认为我们的优先级会更高点,所有会使用咱们自己的,如果exposedObject == bean那么表示咱们自己没有修改bean对象,于是就使用Object earlySingletonReference = getSingleton(beanName, false)这个方法返回的值.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)