Spring源碼分析-----加載bean

先看下簡(jiǎn)單的Spring應(yīng)用

public static void main(String[] args) {
   BeanFactory bf = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));
   TestBean bean = (TestBean)bf.getBean("test");
   bean.test();
 }

獲取bean的時(shí)候調(diào)用getBean方法,跟蹤源碼發(fā)現(xiàn)最后調(diào)用的是doGetBean方法

public Object getBean(String name) throws BeansException {
   return doGetBean(name, null, null, false);
}

下面我們?cè)敿?xì)來看下doGetBean方法

獲取Bean對(duì)象整體流程

protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
      @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
   /*進(jìn)行beanName轉(zhuǎn)換,有兩個(gè)原因
    *1)bean配置的時(shí)候可以配置別名懦傍,name可能是別名怨绣,需要轉(zhuǎn)換成對(duì)應(yīng)的真實(shí)beanName
    *2)name可能是以&字符開頭的背亥,表明調(diào)用者想要獲取FactoryBean本身览闰,而非FactoryBean實(shí)現(xiàn)類所創(chuàng)建的bean
    */
   final String beanName = transformedBeanName(name);
   Object bean;

   // Eagerly check singleton cache for manually registered singletons.
   /*
    *
    * 檢查緩存中或者實(shí)例工廠中是否有實(shí)例對(duì)象
    *
    * 因子在創(chuàng)建單例bean的時(shí)候回存在依賴注入的情況吨娜,而在創(chuàng)建依賴的時(shí)候?yàn)榱吮苊庋h(huán)依賴
    * Spring創(chuàng)建bean的原則是不等bean創(chuàng)建完成就會(huì)將創(chuàng)建bean的ObjectFactory提早曝光
    * 也就是將ObjectFactory加入到緩存中麻顶,一旦下個(gè)bean創(chuàng)建時(shí)需要依賴上個(gè)bean則直接使用ObjectFactory
    */

   //直接嘗試從緩存中獲取或者singletonFactories中的ObjectFactory中獲取
   Object sharedInstance = getSingleton(beanName);

   /*
    *如果sharedInstance為空赦抖,則說明緩存中沒有對(duì)應(yīng)的實(shí)例,表明這個(gè)類還沒創(chuàng)建
    * BeanFactory并不會(huì)在一開始就將所有的單例bean實(shí)例化好辅肾,而且在調(diào)用getBean獲取
    * bean時(shí)再實(shí)例化队萤,也即是懶加載
    *
    * getBean有很多重載方法,在首次獲取某個(gè)bean時(shí)宛瞄,可以傳入用于初始化bean的參數(shù)數(shù)組(args)浮禾,BeanFactory會(huì)根據(jù)這些
    * 參數(shù)去匹配何時(shí)的構(gòu)造方法構(gòu)造bean實(shí)例。當(dāng)然份汗,如果單例bean早已創(chuàng)建好盈电,這里的args就沒用了
    *
    */
   if (sharedInstance != null && args == null) {
      if (logger.isTraceEnabled()) {
         if (isSingletonCurrentlyInCreation(beanName)) {
            logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
                  "' that is not fully initialized yet - a consequence of a circular reference");
         }
         else {
            logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
         }
      }
      /*
       *如果sharedInstance是普通的單例bean,下面的方法會(huì)直接返回
       * 但是如果sharedInstance是FactoryBean類型杯活,則需要調(diào)用getObject工廠方法獲取
       * 真正的bean實(shí)例匆帚。如果用戶想要獲取FactoryBean本身,這里也不會(huì)特別的處理旁钧,直接返回即可
       */
      bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
   }

   /*
    * 如果上面的條件不滿足吸重,則表明sharedInstance可能為空,此時(shí)beanName對(duì)應(yīng)的bean實(shí)例
    * 可能還沒創(chuàng)建
    * 還有一種可能歪今,如果當(dāng)前容器有父容器嚎幸,beanName對(duì)應(yīng)的bean實(shí)例可能在父容器中被創(chuàng)建
    * 所以在創(chuàng)建實(shí)例前,需要先去父容器里檢查一下
    */
   else {
      // Fail if we're already creating this bean instance:
      // We're assumably within a circular reference.
      //BeanFactory不緩存Prototype類型的bean寄猩,無法處理該類型的循環(huán)依賴問題
      if (isPrototypeCurrentlyInCreation(beanName)) {
         throw new BeanCurrentlyInCreationException(beanName);
      }

      // Check if bean definition exists in this factory.
      //如果sharedInstance為空嫉晶,則到父容器中查詢bean的實(shí)例
      BeanFactory parentBeanFactory = getParentBeanFactory();
      //如果beanDefinitionMap中也就是在所有已經(jīng)加載過的類中不包括beanName則嘗試從parentFactory中查找
      if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
         // Not found -> check parent.
         //獲取name對(duì)應(yīng)的beanName,如果name是以&字符開頭田篇,則返回&+beanName
         String nameToLookup = originalBeanName(name);
         //父容器是AbstractBeanFactory類型替废,調(diào)用父容器的doGetBean方法查找
         if (parentBeanFactory instanceof AbstractBeanFactory) {
            return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
                  nameToLookup, requiredType, args, typeCheckOnly);
         }
         //根據(jù)args是否為空,已決定調(diào)用父容器哪個(gè)方法獲取bean
         else if (args != null) {
            // Delegation to parent with explicit args.
            return (T) parentBeanFactory.getBean(nameToLookup, args);
         }

         else if (requiredType != null) {
            // No args -> delegate to standard getBean method.
            return parentBeanFactory.getBean(nameToLookup, requiredType);
         }
         else {
            return (T) parentBeanFactory.getBean(nameToLookup);
         }
      }
      //如果不是僅僅做類型檢查則是創(chuàng)建bean泊柬,這里要進(jìn)行記錄
      if (!typeCheckOnly) {
         markBeanAsCreated(beanName);//標(biāo)記當(dāng)前beanName對(duì)應(yīng)的bean已創(chuàng)建
      }

      try {
         //合并父BeanDefinition和子BeanDefinition
         //將存在XML配置文件的GenericBeanDefinition轉(zhuǎn)成RootBeanDefinition椎镣,如果指定BeanName是子bean的話同時(shí)合并父類的相關(guān)屬性
         final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
         checkMergedBeanDefinition(mbd, beanName, args);

         // Guarantee initialization of beans that the current bean depends on.
         //獲取bean所有的dependsOn,如果有依賴兽赁,則先加載依賴的bean
         String[] dependsOn = mbd.getDependsOn();
         if (dependsOn != null) {
            for (String dep : dependsOn) {
               /*
                  檢測(cè)是否存在循環(huán)依賴
                */
               if (isDependent(beanName, dep)) {
                  throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
               }
               //注冊(cè)依賴記錄
               registerDependentBean(dep, beanName);
               try {
                  //先加載依賴的bean
                  getBean(dep);
               }
               catch (NoSuchBeanDefinitionException ex) {
                  throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
               }
            }
         }

         // Create bean instance.
         if (mbd.isSingleton()) {
            /*
             *這里并沒有直接調(diào)用 createBean 方法創(chuàng)建bean實(shí)例状答,而且通過getSingleton(String,ObjectFactory)方法獲取bean實(shí)例
             * getSingleton(String,ObjectFactory)方法會(huì)在內(nèi)部調(diào)用ObjectFactory的getObject()方法創(chuàng)建bean
             * 并在創(chuàng)建完成后冷守,將bean放入緩存中
             */
            sharedInstance = getSingleton(beanName, () -> {
               try {
                  //創(chuàng)建bean實(shí)例
                  return createBean(beanName, mbd, args);
               }
               catch (BeansException ex) {
                  // Explicitly remove instance from singleton cache: It might have been put there
                  // eagerly by the creation process, to allow for circular reference resolution.
                  // Also remove any beans that received a temporary reference to the bean.
                  destroySingleton(beanName);
                  throw ex;
               }
            });
            //如果bean是FactoryBean類型,則調(diào)用工廠方法獲取真正的bean實(shí)例剪况,否則直接返回bean實(shí)例
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);ge'?
         }

         //創(chuàng)建Prototype類型的bean實(shí)例
         else if (mbd.isPrototype()) {
            // It's a prototype -> create a new instance.
            Object prototypeInstance = null;
            try {
               beforePrototypeCreation(beanName);
               prototypeInstance = createBean(beanName, mbd, args);
            }
            finally {
               afterPrototypeCreation(beanName);
            }
            bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
         }

         //創(chuàng)建其他類型的bean實(shí)例
         else {
            String scopeName = mbd.getScope();
            final Scope scope = this.scopes.get(scopeName);
            if (scope == null) {
               throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
            }
            try {
               Object scopedInstance = scope.get(beanName, () -> {
                  beforePrototypeCreation(beanName);
                  try {
                     return createBean(beanName, mbd, args);
                  }
                  finally {
                     afterPrototypeCreation(beanName);
                  }
               });
               bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
            }
            catch (IllegalStateException ex) {
               throw new BeanCreationException(beanName,
                     "Scope '" + scopeName + "' is not active for the current thread; consider " +
                     "defining a scoped proxy for this bean if you intend to refer to it from a singleton",
                     ex);
            }
         }
      }
      catch (BeansException ex) {
         cleanupAfterBeanCreationFailure(beanName);
         throw ex;
      }
   }

   // Check if required type matches the type of the actual bean instance.
   //進(jìn)行類型轉(zhuǎn)換
   if (requiredType != null && !requiredType.isInstance(bean)) {
      try {
         T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
         if (convertedBean == null) {
            throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
         }
         return convertedBean;
      }
      catch (TypeMismatchException ex) {
         if (logger.isTraceEnabled()) {
            logger.trace("Failed to convert bean '" + name + "' to required type '" +
                  ClassUtils.getQualifiedName(requiredType) + "'", ex);
         }
         throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
      }
   }
   return (T) bean;
}
doGetBean整體流程.png

beanName轉(zhuǎn)換

protected String transformedBeanName(String name) {
   return canonicalName(BeanFactoryUtils.transformedBeanName(name));
}

public static String transformedBeanName(String name) {
        Assert.notNull(name, "'name' must not be null");
        if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
            return name;
        }
        return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
            do {
                //處理掉beanName中的&字符
                beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
            }
            while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
            return beanName;
        });
    }

    /*
     *  該方法用于轉(zhuǎn)換別名
     */
    public String canonicalName(String name) {
        String canonicalName = name;
        // Handle aliasing...
        String resolvedName;
        /**
         * 這里采用循環(huán)處理的原因是教沾,存在別名指向別名的可能
         * <bean id="hello" class="com.df.Hello" />
         * <alias name="hello" alias="aliasA" />
         * <alias name="aliasA" alias="aliasB" />
         * alisaB --> aliasA --> hello
         */
        do {
            resolvedName = this.aliasMap.get(canonicalName);
            if (resolvedName != null) {
                canonicalName = resolvedName;
            }
        }
        while (resolvedName != null);
        return canonicalName;
    }


在Spring容器中,是按照BeanName和Bean對(duì)象一樣對(duì)應(yīng)進(jìn)行存儲(chǔ)的译断,通過beanName可以直接找到對(duì)應(yīng)的bean對(duì)象授翻。在配置時(shí),支持別名的方式進(jìn)行配置孙咪。通過別名獲取bean時(shí)堪唐,先找到別名對(duì)應(yīng)的真實(shí)BeanName,然后再通過beanName進(jìn)行查找

從緩存中獲取單例bean

public Object getSingleton(String beanName) {
   return getSingleton(beanName, true);
}

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        //嘗試從緩存中獲取單例bean實(shí)例
        Object singletonObject = this.singletonObjects.get(beanName);
        /*
         * singletonObject為空翎蹈,說明還沒創(chuàng)建淮菠,或者還沒有完全創(chuàng)建好
         * isSingletonCurrentlyInCreation是判斷beanName對(duì)應(yīng)的bean是否正在創(chuàng)建中
         * 解決bean之間的循環(huán)依賴
         */
        if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
            synchronized (this.singletonObjects) {
                //earlySingletonObjects中獲取提前曝光的bean 用于處理循環(huán)引用
                singletonObject = this.earlySingletonObjects.get(beanName);
                // 如果如果 singletonObject = null,且允許提前曝光 bean 實(shí)例荤堪,則從相應(yīng)的 ObjectFactory 獲取一個(gè)原始的(raw)bean(尚未填充屬性)
                if (singletonObject == null && allowEarlyReference) {
                    //獲取相應(yīng)的工廠類
                    ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                    if (singletonFactory != null) {
                        //提前曝光bean實(shí)例 合陵,用于解決循環(huán)依賴
                        singletonObject = singletonFactory.getObject();
                        //放入緩存中 這樣如果其他的bean依賴當(dāng)前bean,則可以從earlySingletonObjects中獲取
                        this.earlySingletonObjects.put(beanName, singletonObject);
                        this.singletonFactories.remove(beanName);
                    }
                }
            }
        }
        return singletonObject;
    }

在Spring中澄阳,有很多緩存

singletonObjects:用于存放單例bean對(duì)象

earlySingletonObjects:也是用于存放單例bean對(duì)象拥知,它用于解決循環(huán)依賴

singletonFactories:存放創(chuàng)建bean對(duì)象的factoryObject

對(duì)于單類對(duì)象,由于每次獲取的都是同一個(gè)對(duì)象碎赢,為了提供效率低剔,Spring會(huì)將這些對(duì)象緩存起來。Spring容器中絕大多數(shù)對(duì)象都是單類的肮塞,所以每次調(diào)用getBean方法時(shí)襟齿,首先嘗試從緩存中獲取對(duì)應(yīng)的bean對(duì)象,提高了性能枕赵。

對(duì)于循環(huán)依賴的問題猜欺,后面專門會(huì)說

從實(shí)例中獲取bean對(duì)象

protected Object getObjectForBeanInstance(
      Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {

   //如果name以&開頭,但beanInatance卻不是FactoryBean拷窜,則認(rèn)為有問題
   if (BeanFactoryUtils.isFactoryDereference(name)) {
      if (beanInstance instanceof NullBean) {
         return beanInstance;
      }
      if (!(beanInstance instanceof FactoryBean)) {
         throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
      }
   }

    /*
      上面判斷通過后替梨,表明beanInstance可能是一個(gè)普通的bean,也可能是一個(gè)FactoryBean
      如果是一個(gè)普通的bean装黑,這里直接返回beanInstance即可
      如果name是以&開頭的,則說明用戶最終想要獲取的是Factory本身弓熏,也直接返回
      如果是FactoryBean恋谭,則要調(diào)用工廠方法生成一個(gè)實(shí)例
    */
   if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
      return beanInstance;
   }

   Object object = null;
   if (mbd == null) {
      /*
         如果mbd為空,則從緩存中加載bean挽鞠。FactoryBean生成的單例bean會(huì)被緩存
         在factoryBeanObjectCache集合中疚颊,不用每次都創(chuàng)建
       */
      object = getCachedObjectForFactoryBean(beanName);
   }
   if (object == null) {
      // Return bean instance from factory.
      //到了這里狈孔,可以保證是FactoryBean類型了
      FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
      // Caches object obtained from FactoryBean if it is a singleton.
      //如果mbd為空。則判斷是否存在名字為beanName的beanDefine
      if (mbd == null && containsBeanDefinition(beanName)) {
         //合并BeanDefinition
         mbd = getMergedLocalBeanDefinition(beanName);
      }
      //跟Aop相關(guān)材义,如果被Aop增強(qiáng)了均抽,則為true
      //是否是用戶定義的而不是應(yīng)用程序本事定義的
      boolean synthetic = (mbd != null && mbd.isSynthetic());
      //調(diào)用getObjectFromFactoryBean
      object = getObjectFromFactoryBean(factory, beanName, !synthetic);
   }
   return object;
}

beanInstance只是初始狀態(tài)的bean,不一定是最終我們想要的bean其掂。如果是FactoryBean類型油挥,beanInstance只是FactoryBean的初始狀態(tài),我們正在需要的bean需要調(diào)用FactoryBean的factory-method方法來獲取

處理加載依賴

在bean配置中,可以通過depends-on屬性來配置加載依賴類款熬。此時(shí)Srping會(huì)優(yōu)先加載依賴的類深寥,然后再加載當(dāng)前bean

<bean id="sysinit" class="SystemInit">
<bean id="manager" class="CacheManager"  depends-on="sysinit"/>
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
   for (String dep : dependsOn) {
      /*
         檢測(cè)是否存在循環(huán)依賴,兩個(gè)bean
       */
      if (isDependent(beanName, dep)) {
         throw new BeanCreationException(mbd.getResourceDescription(), beanName,
               "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
      }
      //注冊(cè)依賴記錄
      registerDependentBean(dep, beanName);
      try {
         //先加載依賴的bean
         getBean(dep);
      }
      catch (NoSuchBeanDefinitionException ex) {
         throw new BeanCreationException(mbd.getResourceDescription(), beanName,
               "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
      }
   }
}

代碼邏輯很簡(jiǎn)單,從當(dāng)前bean的定義中獲取依賴類贤牛,然后注冊(cè)依賴記錄惋鹅,加載依賴類

根據(jù)不同的scope獲取bean對(duì)象

獲取單類bean
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
   Assert.notNull(beanName, "Bean name must not be null");
   //全局變量需要同步
   synchronized (this.singletonObjects) {
      //首先檢測(cè)beanName對(duì)應(yīng)的bean是否已經(jīng)加載過,因?yàn)閟ingleton模式其實(shí)就是復(fù)用以創(chuàng)建的bean殉簸,所以這一步是必須的
      Object singletonObject = this.singletonObjects.get(beanName);
      //只有沒加載過闰集,才能進(jìn)行初始化
      if (singletonObject == null) {
         if (this.singletonsCurrentlyInDestruction) {
            throw new BeanCreationNotAllowedException(beanName,
                  "Singleton bean creation not allowed while singletons of this factory are in destruction " +
                  "(Do not request a bean from a BeanFactory in a destroy method implementation!)");
         }
         if (logger.isDebugEnabled()) {
            logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
         }
         //創(chuàng)建前的操作 將此beanName加入singletonsCurrentlyInCreation緩存中, 標(biāo)記此bean正在創(chuàng)建中
         beforeSingletonCreation(beanName);
         boolean newSingleton = false;
         boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
         if (recordSuppressedExceptions) {
            this.suppressedExceptions = new LinkedHashSet<>();
         }
         try {
            //初始化bean
            singletonObject = singletonFactory.getObject();
            newSingleton = true;
         }
         catch (IllegalStateException ex) {
            // Has the singleton object implicitly appeared in the meantime ->
            // if yes, proceed with it since the exception indicates that state.
            singletonObject = this.singletonObjects.get(beanName);
            if (singletonObject == null) {
               throw ex;
            }
         }
         catch (BeanCreationException ex) {
            if (recordSuppressedExceptions) {
               for (Exception suppressedException : this.suppressedExceptions) {
                  ex.addRelatedCause(suppressedException);
               }
            }
            throw ex;
         }
         finally {
            if (recordSuppressedExceptions) {
               this.suppressedExceptions = null;
            }
            //從singletonsCurrentlyInCreation中刪除
            afterSingletonCreation(beanName);
         }
         if (newSingleton) {
            //加入到緩存 并刪除創(chuàng)建過程中的輔助狀態(tài)
            addSingleton(beanName, singletonObject);
         }
      }
      return singletonObject;
   }
}

1)首先鎖住singletonObjects防止并發(fā)操作

2)再次確認(rèn)對(duì)應(yīng)的bean對(duì)象沒有創(chuàng)建

3)在創(chuàng)建前標(biāo)記beanName對(duì)應(yīng)的bean正在創(chuàng)建中般卑,上面從緩存中獲取單例的時(shí)候武鲁,可能會(huì)判斷

4)然后調(diào)用singletonFactory的getObejct方法創(chuàng)建bean對(duì)象

5)創(chuàng)建完成之后,從singletonsCurrentlyInCreation中刪除beanName

6)如果當(dāng)前bean是第一次創(chuàng)建對(duì)象椭微,則將bean對(duì)象加入到單例緩存中

Prototype類型bean的獲取

Prototype類型的bean每次獲取都會(huì)創(chuàng)建一個(gè)新的bean對(duì)象洞坑,代碼很簡(jiǎn)單,就是在對(duì)象創(chuàng)建前標(biāo)記正在創(chuàng)建蝇率,創(chuàng)建后刪除此標(biāo)記

else if (mbd.isPrototype()) {
   // It's a prototype -> create a new instance.
   Object prototypeInstance = null;
   try {
      beforePrototypeCreation(beanName);
      prototypeInstance = createBean(beanName, mbd, args);
   }
   finally {
      afterPrototypeCreation(beanName);
   }
   bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
其他scope類型bean的獲取

和Prototype類型bean獲取的區(qū)別在于會(huì)從scope中獲取

else {
      String scopeName = mbd.getScope();
      final Scope scope = this.scopes.get(scopeName);
      if (scope == null) {
         throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
      }
      try {
         Object scopedInstance = scope.get(beanName, () -> {
            beforePrototypeCreation(beanName);
            try {
               return createBean(beanName, mbd, args);
            }
            finally {
               afterPrototypeCreation(beanName);
            }
         });
         bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
      }
      catch (IllegalStateException ex) {
         throw new BeanCreationException(beanName,
               "Scope '" + scopeName + "' is not active for the current thread; consider " +
               "defining a scoped proxy for this bean if you intend to refer to it from a singleton",
               ex);
      }
   }
}

類型轉(zhuǎn)換

當(dāng)參數(shù)requiredType不為空迟杂,且bean對(duì)象不是requiredType類型實(shí)例時(shí),就會(huì)進(jìn)行類型緩存本慕,requiredType在調(diào)用getBean方法時(shí)傳入排拷,例如:

applicationContext.getBean("test",TestBean.class);
//進(jìn)行類型轉(zhuǎn)換
if (requiredType != null && !requiredType.isInstance(bean)) {
   try {
      T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
      if (convertedBean == null) {
         throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
      }
      return convertedBean;
   }
   catch (TypeMismatchException ex) {
      if (logger.isTraceEnabled()) {
         logger.trace("Failed to convert bean '" + name + "' to required type '" +
               ClassUtils.getQualifiedName(requiredType) + "'", ex);
      }
      throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
   }
}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市锅尘,隨后出現(xiàn)的幾起案子监氢,更是在濱河造成了極大的恐慌,老刑警劉巖藤违,帶你破解...
    沈念sama閱讀 212,383評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件浪腐,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡顿乒,警方通過查閱死者的電腦和手機(jī)议街,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來璧榄,“玉大人特漩,你說我怎么就攤上這事吧雹。” “怎么了涂身?”我有些...
    開封第一講書人閱讀 157,852評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵雄卷,是天一觀的道長。 經(jīng)常有香客問我蛤售,道長丁鹉,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,621評(píng)論 1 284
  • 正文 為了忘掉前任悍抑,我火速辦了婚禮鳄炉,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘搜骡。我一直安慰自己拂盯,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,741評(píng)論 6 386
  • 文/花漫 我一把揭開白布记靡。 她就那樣靜靜地躺著谈竿,像睡著了一般。 火紅的嫁衣襯著肌膚如雪摸吠。 梳的紋絲不亂的頭發(fā)上空凸,一...
    開封第一講書人閱讀 49,929評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音寸痢,去河邊找鬼呀洲。 笑死,一個(gè)胖子當(dāng)著我的面吹牛啼止,可吹牛的內(nèi)容都是我干的道逗。 我是一名探鬼主播,決...
    沈念sama閱讀 39,076評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼献烦,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼滓窍!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起巩那,我...
    開封第一講書人閱讀 37,803評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤吏夯,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后即横,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體噪生,經(jīng)...
    沈念sama閱讀 44,265評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,582評(píng)論 2 327
  • 正文 我和宋清朗相戀三年东囚,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了杠园。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,716評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖抛蚁,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情惕橙,我是刑警寧澤瞧甩,帶...
    沈念sama閱讀 34,395評(píng)論 4 333
  • 正文 年R本政府宣布,位于F島的核電站弥鹦,受9級(jí)特大地震影響肚逸,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜彬坏,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,039評(píng)論 3 316
  • 文/蒙蒙 一朦促、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧栓始,春花似錦务冕、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至落恼,卻和暖如春箩退,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背佳谦。 一陣腳步聲響...
    開封第一講書人閱讀 32,027評(píng)論 1 266
  • 我被黑心中介騙來泰國打工戴涝, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人钻蔑。 一個(gè)月前我還...
    沈念sama閱讀 46,488評(píng)論 2 361
  • 正文 我出身青樓啥刻,卻偏偏與公主長得像,于是被迫代替她去往敵國和親矢棚。 傳聞我的和親對(duì)象是個(gè)殘疾皇子郑什,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,612評(píng)論 2 350

推薦閱讀更多精彩內(nèi)容