ListableBeanFactory#getBeanNamesForType(Class<?>)
这个方法的逻辑在对 FactoryBean 进行判断时,会使用 FactoryBean 的生成的对象的类型进行判断
- BD 的属性数据 AttributeAccessor.getAttribute(FactoryBean.OBJECT_TYPE_ATTRIBUTE)
- 反射创建对象并调用 FactoryBean#getObjectType
- 实例化 Bean 并调用 FactoryBean#getObjectType
那么对于 MyBatis 这种,直接实例化 MapperFactoryBean 的 getObjectType 是不会返回确定的类型的,只有1和3会返回,如果在创建 BeanDefinition
时没有 setAttribute,那么就会发生提前实例化的问题
问题又在与这个提前实例化失败时 Spring 不会抛出异常停止应用的启动,而是将底层的异常捕获并打印 debug 日志
切实遇到的问题
公司在 MyBatis-Spring 的基础上自己进行了 SpringBoot 风格的适配,但是在创建 BeanDefinition 时没有 setAttribute,导致如果
XML的Mapper啊这些写得有问题,那么 MapperFactoryBean 在实例化时会依赖相关的 MyBatis 的 Bean 的构建,当构建失败,不会停止应用。
于是产生的问题是
- Dao/Mapper 都生成了对应的 MapperFactoryBean
- getBeanNamesForType 在没有找到时会遍历它们判断
- 实例化对应的 MapperFactoryBean -> 扫描 XML 文件 -> 解析报错 -> 抑制异常
- 重复 3 直到处理完毕
于是就造成了一旦 XML 写错,控制台就会打印大量日志,给人感觉像是一直死循环处理一样的
解决方案
实际上 Spring 和 MyBatis 在后续版本已经解决了这个这个问题,就是 setAttribute,但是公司的版本没有继续迭代
标签:XML,MapperFactoryBean,实例,09,setAttribute,FactoryBean,MyBatis From: https://www.cnblogs.com/chenxingyang/p/18139472