分享

Mybatis源码分析(四):属性接口之objectFactory

 云梦天涯rqxe9h 2018-02-24

一. objectFactory在spring配置文件中的配置


bean id='sqlSessionFactory' class='org.mybatis.spring.SqlSessionFactoryBean'>
  property name='objectFactory' ref='objectFactory'/>
   
bean>

bean id='objectFactory'
class='com.zzy.mybatisex.objectfactory.MyObectFactory'>

     
bean>


二.源码分析


先看官方文档中ObjectFactory的含义:


MyBatis 每次创建结果对象的新实例时,它都会使用一个对象工厂(ObjectFactory)实例来完成。 默认的对象工厂需要做的仅仅是实例化目标类,要么通过默认构造方法,要么在参数映射存在的时候通过参数构造方法来实例化。 如果想覆盖对象工厂的默认行为,则可以通过创建自己的对象工厂来实现。

 

这个对象是mybatis对象实例化用的,本质上内部也是通过构造器来完成的。这个实例对象创建的过程是通过DefaultObjectFactory这类来完成的。但是如果默认的对象工厂无法满足需求,可以定义自己的对象工厂(下面会用实例介绍)。


objectFactory相关配置在源码中加载位置(buildSqlSessionFactory()中):


if (this.objectFactory != null) {
     configuration.setObjectFactory(this.objectFactory);
}


通过configuration.setObjectFactory(this.objectFactory)可以找到加载过程,configuration数据中心对objectFactory就行了配置,

  protected ObjectFactory objectFactory = new DefaultObjectFactory();

 

DefaultObjectFactory就是我们要找的默认对象工厂(不配置的情况下就会使用配置对象工厂)


DefaultObjectFactory结构:

public class DefaultObjectFactory implements ObjectFactory, Serializable {


这个类实现自接口ObjectFactory。


ObjectFactory接口源码:


public interface ObjectFactory {

 /**
  * Sets configuration properties.
  * @param properties configuration properties
  */

 void setProperties(Properties properties);

 /**
  * Creates a new object with default constructor.
  * @param type Object type
  * @return
  */

  T create(Class type);

 /**
  * Creates a new object with the specified constructor and params.
  * @param type Object type
  * @param constructorArgTypes Constructor argument types
  * @param constructorArgs Constructor argument values
  * @return
  */

  T create(Class type, List<>> constructorArgTypes, List constructorArgs);
 
 /**
  * Returns true if this object can have a set of other objects.
  * It's main purpose is to support non-java.util.Collection objects like Scala collections.
  *
  * @param type Object type
  * @return whether it is a collection or not
  * @since 3.1.0
  */

  boolean isCollection(Class type);

}



实现类DefaultObjectFactory源码:


public class DefaultObjectFactory implements ObjectFactory, Serializable {

 private static final long serialVersionUID = -8855120656740914948L;

 @Override
 public T create(Class type) {
   return create(type, null, null);
 }

 @SuppressWarnings('unchecked')
 @Override
 public T create(Class type, List<>> constructorArgTypes, ListObject> constructorArgs) {
   Class classToCreate = resolveInterface(type);
   // we know types are assignable
   return (T) instantiateClass(classToCreate, constructorArgTypes, constructorArgs);
 }

 @Override
 public void setProperties(Properties properties) {
   // no props for default
 }

  T instantiateClass(Class type, List<>> constructorArgTypes, ListObject> constructorArgs) {
 
    //通过构造器创建的过程,代码太多,省去了,具体可以去DefaultObjectFactory 中看
 
 }

 protected Class resolveInterface(Class type) {
   Class classToCreate;
   if (type == List.class || type == Collection.class || type == Iterable.class) {
     classToCreate = ArrayList.class;
   } else if (type == Map.class) {
     classToCreate = HashMap.class;
   } else if (type == SortedSet.class) { // issue #510 Collections Support
     classToCreate = TreeSet.class;
   } else if (type == Set.class) {
     classToCreate = HashSet.class;
   } else {
     classToCreate = type;
   }
   return classToCreate;
}

 @Override
 public boolean isCollection(Class type) {
   return Collection.class.isAssignableFrom(type);
 }

}


从上面的create方法代码可以看出classToCreate是要创建的类,这个类是通过resolveInterface获取到的,然后通过instantiateClass利用反射机制创建classToCreate的对象,这样就完成了对象实例化过程。


三. 实例扩展

(配置过程参考第一点)

创建对象工厂,必须继承defaultObjectFactory

 

代码实现过程:

/**
* @author zhaozhiyong
*
*/

public class MyObectFactory extends DefaultObjectFactory {

 @Override
 public Object create(Class type) {
   if (type.equals(User.class)){
     User u = (User)super.create(type);
     u.setId(1);
     u.setName('zhaozhiyong');
     u.setSex(1);
     return u;
   }
   return super.create(type);
 }

 @Override
 public void setProperties(Properties properties) {
   Iterator iterator = properties.keySet().iterator();
   while (iterator.hasNext()){
      String keyValue = String.valueOf(iterator.next());
      System.out.println(properties.getProperty(keyValue));
   }
   super.setProperties(properties);
 }

 @Override
 public boolean isCollection(Class type) {
   return super.isCollection(type);
 }

}

单元测试用例代码:


MyObectFactory myObectFactory = new MyObectFactory();
User user =(User)myObectFactory.create(User.class);
System.out.println('User[id ='+user.getId()+'  name='+user.getName()+'  age='+user.getSex()+']');//控制台


Test结果:

通过结果可以看出,自定义的对象工厂已经对user实例化了,所以在DefaultObjectFactory无法满足要求的时候,可以自定义对象工厂完成一些特殊的实例化。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多