spring的FactoryBean

(以下内容翻译自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 {}
原文地址:https://www.cnblogs.com/allenwas3/p/8413069.html