(以下内容翻译自spring/docs/3.2.18.RELEASE)
为具有工厂属性的对象实现FactoryBean接口。
FactoryBean接口是spring IoC 容器实例化逻辑的一点补充。
如果你有一个复杂的对象,更适合用java代码描述而不是xml,你可以创建自己的FactoryBean,
并在类中写复杂的实例化代码,然后把自定义的FactoryBean加入到spring容器中。
示例:
<bean id="myBean" class="com.dao.MyFactoryBean"></bean>
public class ComplexObj { public Date date; public ComplexObj() { System.out.println("ComplexObj construtcor"); } }
public class MyFactoryBean implements FactoryBean<ComplexObj> { public MyFactoryBean() { System.out.println("MyFactoryBean constructor"); } @Override public ComplexObj getObject() throws Exception { ComplexObj obj = new ComplexObj(); obj.date = new Date(); return obj; } @Override public Class<?> getObjectType() { return ComplexObj.class; } @Override public boolean isSingleton() { return false; } }
getBean("myBean"); //返回FactoryBean创建的对象
getBean("&myBean"); //返回FactoryBean对象自身
Object bean = appCtx.getBean("myBean"); System.out.println(bean); Object bean2 = appCtx.getBean("&myBean"); System.out.println(bean2);
1. spring容器创建MyFactoryBean的调用栈,就是一个普通单例bean的创建过程:
2. 创建工厂产品的调用栈:
AbstractBeanFactory
// AbstractBeanFactory protected <T> T doGetBean( final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException { final String beanName = transformedBeanName(name); Object bean; // Eagerly check singleton cache for manually registered singletons. Object sharedInstance = getSingleton(beanName); //获取工厂的产品对象,走if分支 // sharedInstance是MyFactoryBean对象 if (sharedInstance != null && args == null) { if (logger.isDebugEnabled()) { if (isSingletonCurrentlyInCreation(beanName)) { logger.debug("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference"); } else { logger.debug("Returning cached instance of singleton bean '" + beanName + "'"); } } bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); } else { ... } // Check if required type matches the type of the actual bean instance. if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) { try { return getTypeConverter().convertIfNecessary(bean, requiredType); } catch (TypeMismatchException ex) { if (logger.isDebugEnabled()) { logger.debug("Failed to convert bean '" + name + "' to required type [" + ClassUtils.getQualifiedName(requiredType) + "]", ex); } throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); } } return (T) bean; }
延伸:dubbo的ReferenceBean实现了FactoryBean接口,所以启动consumer的时候,只会创建一个FactoryBean,
并不会去创建invoker代理,只有在触发getBean("xxx")操作时,才会真正去创建invoker代理。
public class ReferenceBean<T> extends ReferenceConfig<T> implements FactoryBean, ApplicationContextAware, InitializingBean {}