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 #