前言
在实际开发当中,如果偏向于系统基础架构开发的话,对于FactoryBean的使用应该不会特别陌生。FactoryBean和BeanFactory这二者经常会被拿出来比较,原因在于这二者的名字看起来很容易让人混淆,然而这二者的原理和作用完全不一样。本篇文章将围绕FactoryBean展开源码解析。
FactoryBean接口
public interface FactoryBean<T> {
// 返回创建的bean对象
T getObject() throws Exception;
// bean对象的Class类型
Class<?> getObjectType();
// bean对象是否是单例,默认为单例。
default boolean isSingleton() {
return true;
}
}
实现FactoryBean
@Component("myDemoService")
public class MyDemoFactoryBean implements FactoryBean<MyDemoService> {
@Override
public MyDemoService getObject() throws Exception {
return new MyDemoService();
}
@Override
public Class<?> getObjectType() {
return MyDemoService.class;
}
}
我们来写一个类测试一下,看看能够从容器中获取到MyDemoFactoryBean和MyDemoService这两个bean:
@Configuration
@ComponentScan("com.leon.factorybean")
public class Config {
}
public class MyApplication {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Config.class);
String[] myDemoTactoryBeanNames = applicationContext.getBeanNamesForType(MyDemoFactoryBean.class);
String[] myDemoServicBeanNames = applicationContext.getBeanNamesForType(MyDemoService.class);
System.out.println(JsonUtil.convert(myDemoTactoryBeanNames));
System.out.println(JsonUtil.convert(myDemoServicBeanNames));
}
}
执行结果如下:
["&myDemoFactoryBean"]
["myDemoFactoryBean"]
可以看到,确实可以从IOC容器中获取分别获取到MyDemoFactoryBean和MyDemoService这两个bean。这说明:
- FacotryBean也是bean,受IOC容器管理;
- FacotryBean可以生产指定的bean,即FacotryBean#getObject()返回的对象;
- BeanName:默认情况下,FactoryBean的beanName为【&】+ 【类名<首字母小写>】;而它生产的bean的beanName就为【类名<首字母小写>】。
接下来,我们来看看FactoryBean在Spring中是如何解析的。
FactoryBean源码追踪
1.入口
在Spring当如,追踪源码的方式最直接的方式就是通过applicatonContext.getBean方式。
MyDemoFactoryBean myDemoFactoryBean = applicationContext.getBean(MyDemoFactoryBean.class);
2.委托给AbstractApplicationContext#getBean
实际调用的是AbstractApplicationContext#getBean(java.lang.Class),该方法其实也是空壳方法,实际将其委托给BeanFactory的getBean方法。
@Override
public <T> T getBean(Class<T> requiredType) throws BeansException {
assertBeanFactoryActive();
return getBeanFactory().getBean(requiredType);
}
3.再委托给DefaultListableBeanFactory#getBean(java.lang.Class)
getBeanFactory()实际上返回的是DefaultListableBeanFactory实例。到这里可以得知,DefaultListableBeanFactory是Spring当中的Be