Mybatis系列(七)objectFactory源码解析


上篇文章 Mybatis系列(六)typeHandler源码解析,对mybatis的类型转换器有了简单的认识,除了我们使用默认提供的typeHandler之外,在平时的项目中,也经常用到自定义的枚举typeHandler,今天这节我们来看看mybatis的对象工厂(objectFactory)是怎么一回事。

依旧从XMLConfigBuilder解析xml配置文件中的objectFactory节点看起

一、objectFactoryElement源码

    private void objectFactoryElement(XNode context) throws Exception {
        if (context != null) {
        	//type属性,获取type节点指定对应的对象工厂
            String type = context.getStringAttribute("type");
            Properties properties = context.getChildrenAsProperties();
            //创建ObjectFactory,依旧是创建别名的这个方法resolveClass
            ObjectFactory factory = (ObjectFactory)this.resolveClass(type).newInstance();
            factory.setProperties(properties);
            //放入configuration,备用
            this.configuration.setObjectFactory(factory);
        }

    }
ObjectFactory 接口
public interface ObjectFactory {
    void setProperties(Properties var1);

    <T> T create(Class<T> var1);

    <T> T create(Class<T> var1, List<Class<?>> var2, List<Object> var3);

    <T> boolean isCollection(Class<T> var1);
}

从接口的定义看,接口有两个通过反射实现得构造函数,另外,为了使的这个工厂类能接收设置的附带属性,还提供了setProperties()方法。

当创建结果集时,mybatis会使用一个对象工厂来完成创建这个结果集实例。在默认的情况下,mybatis会使用其定义的对象工厂——DefaultObjectFactory来完成相应的工作,有兴趣的可以看一下源码的实现类,其实它创建实例对象最终都是通过instantiateClass()方法能实现的,下边会讲到。

ObjectFactory是不是很简单,看到这里可能会问前两节讲的typeAliasestypeHandler,mybatis都提供了默认的配置,并且支持自定义的typeAliasestypeHandler,那么ObjectFactory是否也支持自定义呢?答案是肯定的。下边我们就创建一个自定义的ObjectFactory——MyObjectFactory

二、自定义ObjectFactory

如果自定义需要实现接口ObjectFactory,并给予配置。在大部分情况下,我们不需要自定义返回规则,因为这些比较复杂容易出错,在更多情况下,都会考虑系统已经实现的DefaultObjectFactory,通过继承它来完成我们需要的工作。

public class MyObjectFactory extends DefaultObjectFactory {

    private static final long serialVersionUID = -7924251036323382165L;

   Logger logger = Logger.getLogger(MyObjectFactory.class);

    private Object temp = null;

    public void setProperties(Properties properties) {
        super.setProperties(properties);
        logger.info("初始化参数:--------"+properties.toString());
    }

    //方法2
    public <T> T create(Class<T> type) {
        T result = super.create(type);
        logger.info("创建对象:--------"+result.toString());
        logger.info("是否和上次创建的是同一个对象:【"+temp.equals(result) +"】");
        return result;
    }

    //方法1
    public <T> T create(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {
        T result = super.create(type, constructorArgTypes, constructorArgs);
        logger.info("创建对象:--------"+result.toString());
        temp = result;
        return result;
    }

    public <T> boolean isCollection(Class<T> type) {
        return super.isCollection(type);
    }
}

三、objectFactory在mybatis-config.xml的配置

    <objectFactory type="com.sean.factory.MyObjectFactory">
        <property name="prop1" value="value1"/>
    </objectFactory>

这样mybatis就会采用配置的MyObjectFactory来生成结果集对象,我们测试一下:

四、自定义objectFactory测试

测试代码,依旧是前几节用过的findUserById

    public void findUserByIdTest(){
        SqlSession sqlSession = getSessionFactory().openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        User user = userMapper.findUserById(1L);
        logger.debug(user.getName());
    }

日志打印:
在这里插入图片描述
如果打断点调试,会发现mybatis创建了一个List对象和一个User对象,它会先调用方法1,然后调用方法2,只是最后生成了同一个对象,所以在写入的判断中,始终返回的是true,因为返回的是同一个User对象,所以它会最后适配为一个User对象,这就是它的工作过程。

为什么会创建一个List对象和一个类对象?请看这个方法

resolveInterface
    protected Class<?> resolveInterface(Class<?> type) {
        Class classToCreate;
        //判读是否集合,比如我们传入User,那么就直接返回类对象
        if (type != List.class && type != Collection.class && type != Iterable.class) {
            if (type == Map.class) {
                classToCreate = HashMap.class;
            } else if (type == SortedSet.class) {
                classToCreate = TreeSet.class;
            } else if (type == Set.class) {
                classToCreate = HashSet.class;
            } else {
            	//直接返回对象
                classToCreate = type;
            }
        } else {
        	//直接返回List对象
            classToCreate = ArrayList.class;
        }

        return classToCreate;
    }

objectFactory节点就讲到这里,平时开发中,用到的也比较少,大致了解下怎么回事即可。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值