01_FACTORY_BEAN
Intro(FactoryBean) #
spring.version = 4.3.7.RELEASE
准备编码 #
解析流程 #
1).
初始化bean对象:在refresh()
里面通过obtainFreshBeanFactory()
方法创建扫描到beanDefinition的顶级工厂。然后通过方法finishBeanFactoryInitialization(beanFactory);
实例化所有非懒加载的所有单例bean,此处就包含这个工厂bean对象。2).
手动通过容器进行获取:例如ToolFactory fb = applicationContext.getBean("&toolFB", ToolFactory.class);
注意要获取工厂对象得加工厂名前缀,不然的话,指定类型就是报错,没有指定ToolFactory.class类型的话就是获取到工厂对象产生的Tool对象。下面会通过代码解释。
首先通过getBean(名字,类型)调用的时候会进入到doGetBean( final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
方法。
方法内部通过transformedBeanName(name);
将传入的带&
符号前缀的name 转换成不带&
的。
然后获取通过beanName获取在第一步中创建的工厂bean的实例。
发现实例非null之后进入到getObjectForBeanInstance(sharedInstance, name, beanName, null);
这个方法里面。这个方法里面决定返回工厂对象ToolFactoryBean还是通过工厂创建的对象Tool。Caution
1).
如果是applicationContext.getBean("toolFB", ToolFactory.class);
这种情况,则下面方法最后判断之前获取到的是Tool对象,因为咱们指定了ToolFactoryBean.class
类型。所以会报错。2).
如果没有指定类型:applicationContext.getBean("toolFB");
则获取Tool对象,并不是工厂bean。3).
进入到getObjectForBeanInstance
方法以后:
3.1 先判断 如果想获取工厂bean对象,但是获取到的示例类型并不属于FactoryBean的话报一个异常。
3.2 然后接着判断,如果是普通对象直接返回,或者name中包含&
也直接返回。这就是获取factoryBean对象要加&
的原因。
3.3 要继续往下走的话,就是属于工厂对象,但是name不包含前缀&
.也就是通过getObjectFromFactoryBean
获取factorybean对象要创建的对象。4).
通过Tool tool1 = applicationContext.getBean(Tool.class);
获取需要通过工厂创建的bean对象解析。
通过debug会进入到getBeanNamesForType(Tool.class)
方法。
并且在isTypeMatch
中通过getTypeForFactoryBean((FactoryBean<?>) beanInstance);
匹配到了。将刚才的beanName:toolFB
返回。
然后在resolveNamedBean
中通过getBean(“toolFB”, Tool.class, args),继续获取bean。此时就会进入到3.3
的情况中。通过工厂bean实例创建对象,并且返回。总结 #
Reference #