• 欢迎访问 winrains 的个人网站!
  • 本网站主要从互联网整理和收集了与Java、网络安全、Linux等技术相关的文章,供学习和研究使用。如有侵权,请留言告知,谢谢!

Spring IoC源码分析之Bean的加载(4):createBean()

Spring winrains 来源:大王叫下 1年前 (2019-10-13) 49次浏览

上一篇文章Spring Ioc 之 Bean的加载(三):各个 scope 的 Bean 创建 我们分析了各个作用域Bean的创建大体流程。这篇文章我们来分析以下创建Bean的关键方法 createBean()

createBean()

代码:

// AbstractAutowireCapableBeanFactory.java
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;
    // Make sure bean class is actually resolved at this point, and
    // clone the bean definition in case of a dynamically resolved Class
    // which cannot be stored in the shared merged bean definition.
    // 判断需要创建的Bean是否可以实例化,即是否可以通过当前的类加载器加载
    Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
    if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
        mbdToUse = new RootBeanDefinition(mbd);
        mbdToUse.setBeanClass(resolvedClass);
    }
    // Prepare method overrides.
    // 校验和准备Bean中的方法覆盖
    try {
        mbdToUse.prepareMethodOverrides();
    } catch (BeanDefinitionValidationException ex) {
        throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(), beanName,
                "Validation of method overrides failed", ex);
    }
    try {
        // Give BeanPostProcessors a chance to return a proxy instead of the target bean
        // instance.
        // 如果Bean配置了初始化前和初始化后的处理器,则试图返回一个需要创建Bean的代理对象
        Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
        if (bean != null) {
            return bean;
        }
    } catch (Throwable ex) {
        throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
                "BeanPostProcessor before instantiation of bean failed", ex);
    }
    try {
        // 创建Bean的入口
        Object beanInstance = doCreateBean(beanName, mbdToUse, args);
        if (logger.isDebugEnabled()) {
            logger.debug("Finished creating instance of bean '" + beanName + "'");
        }
        return beanInstance;
    } catch (BeanCreationException ex) {
        // A previously detected exception with proper bean creation context already...
        throw ex;
    } catch (ImplicitlyAppearedSingletonException ex) {
        // An IllegalStateException to be communicated up to
        // DefaultSingletonBeanRegistry...
        throw ex;
    } catch (Throwable ex) {
        throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
                "Unexpected exception during bean creation", ex);
    }
}

这段代码分为以下几个步骤:

  1. 判断需要创建的Bean是否可以实例化,即是否可以通过当前的类加载器加载
  2. 校验和准备Bean中的方法注入
  3. 如果Bean配置了初始化前和初始化后的处理器,则试图返回一个需要创建Bean的代理对象
  4. 创建Bean
第1步

主要是获取bean的class,并设置到BeanDefinition中

第2步

主要是处理方法注入
代码:

public void prepareMethodOverrides() throws BeanDefinitionValidationException {
    // Check that lookup methods exists.
    // 检测是否存在方法注入,并循环预处理方法注入
    if (hasMethodOverrides()) {
        Set<MethodOverride> overrides = getMethodOverrides().getOverrides();
        synchronized (overrides) {
            // 遍历处理
            for (MethodOverride mo : overrides) {
                prepareMethodOverride(mo);
            }
        }
    }
}

prepareMethodOverride(mo):

protected void prepareMethodOverride(MethodOverride mo) throws BeanDefinitionValidationException {
    // 统计注入的方法个数
    int count = ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName());
    if (count == 0) {
        throw new BeanDefinitionValidationException("Invalid method override: no method with name '"
                + mo.getMethodName() + "' on class [" + getBeanClassName() + "]");
    }
    // 如果为1,则将注入方法标记为未重载
    // 注意:当有多个重载方法时,为了确定调用哪个具体的方法,Spring对重载方法的参数解析是很复杂的
    // 所以,如果注入方法没有被重载这里就将其标记,省去了对方法参数的解析过程,直接调用即可
    else if (count == 1) {
        // Mark override as not overloaded, to avoid the overhead of arg type checking.
        mo.setOverloaded(false);
    }
}

代码读到这里,大家可能有疑问,从代码上看明明是处理的方法重载,但是为什么处理的是方法注入呢?而且如果我们在bean里设置几个方法重载的话,hasMethodOverrides()方法返回的是false。如果我们打开 AbstractBeanDefinition 类的 hasMethodOverrides() 方法,就能打消我们之前的疑问。

public boolean hasMethodOverrides() {
    return (this.methodOverrides != null && !this.methodOverrides.isEmpty());
}

其中methodOverrides是做什么的呢?通过类名AbstractBeanDefinition我们可以发现,该类是BeanDefinition的一个子类,那么它保存的应该是我们解析到的beanDefinition,spring在解析配置文件的时候,如果发现配置了replace-method或者lookup-method那么,就会对应的标签解析,并存入到 AbstractBeanDefinition 的 methodOverrides 属性中,那么当bean实例化的时候,如果检测到了methodOverrides属性不为空,则动态的为当前bean生成代理并使用相应的拦截器对bean做处理,这里大家只要把概念搞清楚即可。

第3步

主要是对bean前置后置处理器的处理,给 BeanPostProcessors 后置处理器一个返回代理对象的机会
详细代码:

protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
    Object bean = null;
    if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
        // Make sure bean class is actually resolved at this point.
        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;
}

如果代理对象不为空,则直接返回代理对象,这一步骤有非常重要的作用,Spring 后续实现 AOP 就是基于这个地方判断的。
这个方法核心就在于 applyBeanPostProcessorsBeforeInstantiation()applyBeanPostProcessorsAfterInitialization() 两个方法,before 为实例化前的后处理器应用,after 为实例化后的后处理器应用。

第4步

doCreateBean()
创建Bean

// 真正创建Bean的方法
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
        throws BeanCreationException {
    // Instantiate the bean.
    // BeanWrapper是对Bean的包装,其接口中所定义的功能很简单包括设置获取被包装的对象,获取被包装bean的属性描述器
    BeanWrapper instanceWrapper = null;
    if (mbd.isSingleton()) {
        // 单例模式,删除factoryBean缓存
        instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
    }
    if (instanceWrapper == null) {
        // 使用合适的实例化策略来创建Bean:工厂方法、构造函数自动注入、简单初始化
        instanceWrapper = createBeanInstance(beanName, mbd, args);
    }
    // 从包装类中获取实例化的Bean
    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 {
                // 调用PostProcessor后置处理器,修改 BeanDefinition
                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.isDebugEnabled()) {
            logger.debug(
                    "Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references");
        }
        // 这里是一个匿名内部类,为了防止循环引用,尽早持有对象的引用
        addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
    }
    // Initialize the bean instance.
    // Bean对象的初始化,依赖注入在此触发
    // 这个exposedObject在初始化完成之后返回作为依赖注入完成后的Bean
    Object exposedObject = bean;
    try {
        // 将Bean实例对象封装,并且Bean定义中配置的属性值赋值给实例对象
        populateBean(beanName, mbd, instanceWrapper);
        // 初始化Bean对象
        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) {
        // 获取指定名称的已注册的单例模式Bean对象
        Object earlySingletonReference = getSingleton(beanName, false);
        if (earlySingletonReference != null) {
            // 根据名称获取的已注册的Bean和正在实例化的Bean是同一个
            if (exposedObject == bean) {
                // 当前实例化的Bean初始化完成
                exposedObject = earlySingletonReference;
            }
            // 当前Bean依赖其他Bean,并且当发生循环引用时不允许新创建实例对象
            else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
                String[] dependentBeans = getDependentBeans(beanName);
                Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
                // 获取当前Bean所依赖的其他Bean
                for (String dependentBean : dependentBeans) {
                    // 对依赖Bean进行类型检查
                    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.");
                }
            }
        }
    }
    // Register bean as disposable.
    // 注册完成依赖注入的Bean
    try {
        registerDisposableBeanIfNecessary(beanName, bean, mbd);
    } catch (BeanDefinitionValidationException ex) {
        throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature",
                ex);
    }
    return exposedObject;
}

代码很长,不过别慌,我们来按步骤分析一波

  1. 如果是单例模式,从factoryBeanInstanceCache 缓存中获取BeanWrapper 实例对象并删除缓存
  2. 调用 createBeanInstance() 实例化 bean
  3. 后置处理
  4. 单例模式的循环依赖处理
  5. 属性填充
  6. 初始化 bean 实例对象
  7. 依赖检查
  8. 注册 DisposableBean

doCreateBean() 完成 bean 的创建和初始化工作,内容太多,比较复杂,这里只列出大致流程,接下来我们将分几篇文章来分别阐述相关内容。

作者:大王叫下

来源:https://juejin.im/post/5d73561fe51d4561b072dd7c


版权声明:文末如注明作者和来源,则表示本文系转载,版权为原作者所有 | 本文如有侵权,请及时联系,承诺在收到消息后第一时间删除 | 如转载本文,请注明原文链接。
喜欢 (1)