(以下内容翻译自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 {}