为何IOC容器未调用FactoryBean的getObjectType()方法?
嘿,这个问题我之前在项目里踩过坑,咱们来唠唠为啥会出现这种情况~
首先得明确一个核心点:Spring并不是只要初始化FactoryBean就会调用getObjectType()方法,它只会在需要获取该FactoryBean生产的对象的类型信息时才会触发这个方法的调用。下面是几个常见的场景和原因:
1. 没有触发需要类型校验的场景
getObjectType()的主要作用是告诉Spring这个FactoryBean最终会产出什么类型的对象,所以只有当Spring需要用到这个类型信息的时候才会调用它,比如:
- 当你用
@Autowired、@Resource等注解按类型注入该对象时; - 调用
BeanFactory.getType("beanName")主动查询Bean的类型时; - 使用
ListableBeanFactory.getBeansOfType(Calendar.class)批量获取某类型Bean时; - 容器启动阶段处理BeanDefinition的类型匹配、依赖检查时。
如果你的代码里只是把FactoryBean注册到了容器,但既没有按类型注入它生产的Calendar,也没有主动查询类型,那Spring完全没必要去调用getObjectType(),自然就看不到它的执行痕迹。
2. 你可能误获取了FactoryBean本身而非它生产的对象
注意:如果你通过BeanFactory的getBean("factoryBeanName")获取对象时,默认拿到的是FactoryBean生产的实例;但如果在名称前加&(比如getBean("&calendarFactoryBean")),拿到的就是FactoryBean本身。这种情况下,Spring不需要知道它生产的对象类型,当然不会调用getObjectType()。
3. 原型模式下的调用时机差异
如果你的FactoryBean的isSingleton()方法返回false(即原型模式),Spring会在每次获取实例前可能检查类型,但如果是单例模式,Spring可能只在第一次需要类型信息的时候调用一次getObjectType(),后续就缓存起来了。如果你的单例实例已经被创建,但之前没触发类型检查,那也不会调用这个方法。
怎么验证?
给你个简单的测试方案,马上就能看到效果:
- 先写一个标准的CalendarFactoryBean实现:
public class CalendarFactoryBean implements FactoryBean<Calendar> { @Override public Calendar getObject() throws Exception { return Calendar.getInstance(); } @Override public Class<?> getObjectType() { System.out.println("嘿!getObjectType()被调用啦~"); return Calendar.class; } @Override public boolean isSingleton() { return true; } }
- 在Spring配置里注册这个FactoryBean(不管是XML还是注解配置都行);
- 新增一个类,通过类型注入Calendar:
@Component public class TestService { @Autowired private Calendar calendar; }
当你启动Spring容器时,为了给TestService注入Calendar,Spring会调用CalendarFactoryBean的getObjectType()来确认类型匹配,这时候你就能看到控制台的输出了!
内容的提问来源于stack exchange,提问作者ALTAF

