Spring源码解析(七)——实例创建(中)

论坛 期权论坛     
选择匿名的用户   2021-5-30 02:14   724   0
<div class="content" id="articleContent">
<div class="ad-wrap">
  <p><a href="https://my.oschina.net/u/2663968/blog/3061697" style="color:#A00;font-weight:bold;">2019独角兽企业重金招聘Python工程师标准&gt;&gt;&gt; </a> <img alt="hot3.png" src="https://beijingoptbbs.oss-cn-beijing.aliyuncs.com/cs/5606289-cf0d92129138e2c138e143696168013a.png"></p>
</div>
<span id="OSC_h2_1"></span>
<h2><strong>前言</strong></h2>
<p>    上一节讲到了,Spring 会根据实例的作用域执行不同的创建逻辑,分别是 Singleton、Prototype、其他 Scope,其中 Singleton 会调用 getSingleton 从缓存中获取,缓存中没有才会创建实例;Prototype 每次都会创建;其他 Scope 会调用 Scope.get 获取,保证各作用域内实例唯一。</p>
<p>    它们的公共创建逻辑都是  <span style="color:#c0392b;">createBean </span>方法。</p>
<p> </p>
<span id="OSC_h2_2"></span>
<h2><strong>源码解读</strong></h2>
<p>    <span style="color:#c0392b;">createBean </span>方法由 <span style="color:#c0392b;">AbstractAutowireCapableBeanFactory </span>实现。</p>
<pre class="blockcode"><code class="language-java">public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
        implements AutowireCapableBeanFactory {

    // bean默认实例化策略 —— Ciglib增强代理
    private InstantiationStrategy instantiationStrategy &#61;
                              new CglibSubclassingInstantiationStrategy();

    &#64;Override
    protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args)
                       throws BeanCreationException {
        if (logger.isDebugEnabled()) {
            logger.debug(&#34;Creating instance of bean &#39;&#34; &#43; beanName &#43; &#34;&#39;&#34;);
        }
        RootBeanDefinition mbdToUse &#61; mbd;

        // 解析获取 bean对应类的 Class对象,并拷贝一份 RootBeanDefinition
        Class&lt;?&gt; resolvedClass &#61; resolveBeanClass(mbd, beanName);
        if (resolvedClass !&#61; null &amp;&amp; !mbd.hasBeanClass() &amp;&amp; mbd.getBeanClassName() !&#61; null) {
            mbdToUse &#61; new RootBeanDefinition(mbd);
            mbdToUse.setBeanClass(resolvedClass);
        }

        /**
         * 对于 methodOverrides的校验,即 lookup-method和 replaced-method
         * 如果指定的方法不存在,会抛出异常
         */
        try {
            mbdToUse.prepareMethodOverrides();
        } catch (BeanDefinitionValidationException ex) {
            throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
                    beanName, &#34;Validation of method overrides failed&#34;, ex);
        }

        try {
            // 让 BeanPostProcessors有机会返回代理而不是目标 bean实例
            Object bean &#61; resolveBeforeInstantiation(beanName, mbdToUse);
            if (bean !&#61; null) {
                return bean;
            }
        } catch (Throwable ex) {
            throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
                    &#34;BeanPostProcessor before instantiation of bean failed&#34;, ex);
        }

        // 创建目标 bean实例
        Object beanInstance &#61; doCreateBean(beanName, mbdToUse, args);
        if (logger.isDebugEnabled()) {
            logger.debug(&#34;Finished creating instance of bean &#39;&#34; &#43; beanName &#43; &#34;&#39;&#34;);
        }
        return beanInstance;
    }
}</code></pre>
<p>    首先会解析出要创建实例的类型,之后是对 <span style="color:#c0392b;">methodOverrides </span>的校验</p>
<ul><li><span style="color:#c0392b;">lookup-method </span>:用于将 bean 的指定方法(name属性),配置指定返回哪些实例(bean属性);</li><li><span style="color:#c0392b;">replaced-method</span> :用于将 bean 的指定方法(name属性),替换为——“实现<span style="color:#c0392b;">MethodReplacer</span>”的对象(replacer属性),即方法替换为实现的 <span style="color:#c0392b;">reimplement </span>方法。</li></ul>
<p>    这些替换的前提就是,被指定的方法一定要存在,这就是校验的目的。之后就有两条线了,一个是代理路线(<span style="color:#c0392b;">resolveBeforeInstantiation</span>),另一个是常规的实例创建路线(<span style="color:#c0392b;">doCreateBean</span>)。</p>
<p> </p>
<span id="OSC_h4_3"></span>
<h4><strong>resolveBeforeInstantiation</strong></h4>
<pre class="blockcode"><code class="language-java">    protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
        Object bean &#61; null;
        if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
            // 判断 bean是否为合成的(即不是应用本身定义的),例如 &lt;aop-config&gt;创建的
            // 判断全局是否注册有 InstantiationAwareBeanPostProcessor(BeanPostProcessor子类)
            if (!mbd.isSynthetic() &amp;&amp; hasInstantiationAwareBeanPostProcessors()) {
                // 获取 bean的目标类型
                Class&lt;?&gt; targetType &#61; determineTargetType(beanName, mbd);
                if (targetType !&#61; nu
分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:3875789
帖子:775174
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP