zoukankan      html  css  js  c++  java
  • 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 {}
  • 相关阅读:
    准备 FRM 考试——方法、工具与教训
    930. 和相同的二元子数组 前缀和
    1906. 查询差绝对值的最小值 前缀和
    剑指 Offer 37. 序列化二叉树 二叉树 字符串
    815. 公交路线 BFS
    518. 零钱兑换 II dp 完全背包
    1049. 最后一块石头的重量 II dp
    5779. 装包裹的最小浪费空间 二分
    5778. 使二进制字符串字符交替的最少反转次数 字符串 滑动窗口
    474. 一和零 dp
  • 原文地址:https://www.cnblogs.com/allenwas3/p/8413069.html
Copyright © 2011-2022 走看看