MyBatis-09-FactoryBean的問題

YangDanMua發表於2024-04-16

ListableBeanFactory#getBeanNamesForType(Class<?>)

這個方法的邏輯在對 FactoryBean 進行判斷時,會使用 FactoryBean 的生成的物件的型別進行判斷

  1. BD 的屬性資料 AttributeAccessor.getAttribute(FactoryBean.OBJECT_TYPE_ATTRIBUTE)
  2. 反射建立物件並呼叫 FactoryBean#getObjectType
  3. 例項化 Bean 並呼叫 FactoryBean#getObjectType

那麼對於 MyBatis 這種,直接例項化 MapperFactoryBean 的 getObjectType 是不會返回確定的型別的,只有1和3會返回,如果在建立 BeanDefinition
時沒有 setAttribute,那麼就會發生提前例項化的問題

問題又在與這個提前例項化失敗時 Spring 不會丟擲異常停止應用的啟動,而是將底層的異常捕獲並列印 debug 日誌

切實遇到的問題

公司在 MyBatis-Spring 的基礎上自己進行了 SpringBoot 風格的適配,但是在建立 BeanDefinition 時沒有 setAttribute,導致如果
XML的Mapper啊這些寫得有問題,那麼 MapperFactoryBean 在例項化時會依賴相關的 MyBatis 的 Bean 的構建,當構建失敗,不會停止應用。

於是產生的問題是

  1. Dao/Mapper 都生成了對應的 MapperFactoryBean
  2. getBeanNamesForType 在沒有找到時會遍歷它們判斷
  3. 例項化對應的 MapperFactoryBean -> 掃描 XML 檔案 -> 解析報錯 -> 抑制異常
  4. 重複 3 直到處理完畢

於是就造成了一旦 XML 寫錯,控制檯就會列印大量日誌,給人感覺像是一直死迴圈處理一樣的

解決方案

實際上 Spring 和 MyBatis 在後續版本已經解決了這個這個問題,就是 setAttribute,但是公司的版本沒有繼續迭代