MyBatis之ObjectFactory

2016-10-25 来源: 余林丰 发布在  http://www.cnblogs.com/yulinfeng/p/5995200.html

关于在MyBatis中的ObjectFactory有什么用,在官方文档中有这样的描述(大多数网上的博客都是直接引用这一描述):MyBatis 每次创建结果对象的新实例时,它都会使用一个对象工厂(ObjectFactory)实例来完成。 默认的对象工厂需要做的仅仅是实例化目标类,要么通过默认构造方法,要么在参数映射存在的时候通过参数构造方法来实例化。 如果想覆盖对象工厂的默认行为,则可以通过创建自己的对象工厂来实现。对于像我这种水平的来说,完全就是一脸蒙逼,这到底有啥用?可以说这个对象工厂就是用来创建实体类的,MyBatis有一个DefaultObjectFactory默认对象工厂类,就像上面所说的默认的对象工厂需要做的仅仅是实例化目标类,要么通过默认构造方法,要么在参数映射存在的时候通过参数构造方法来实例化。它不做其他任何的处理。如果我们想在创建实例化一个目标类的时候做点啥其他的动作,可以继承DefaultObjectFactory,覆写父类方法,并在mybatis-config.xml中注册配置这个对象工厂类。

自己实现一个对象工厂如下所示:

 package day_8_mybatis.util;

 import java.util.Collection;
 import java.util.Iterator;
 import java.util.Properties;

 import org.apache.ibatis.reflection.factory.DefaultObjectFactory;

 import day_8_mybatis.pojo.People;

 /**
  * @author turbo
  *
  * 2016年10月24日
  */
 public class ExampleObjectFactory extends DefaultObjectFactory {

     @Override
     public Object create(Class type) {
         if (type.equals(People.class)){
             People p = (People)super.create(type);
             p.setAge(22);
             p.setName("keven");
             return p;
         }
         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 <T> boolean isCollection(Class<T> type) {
         return Collection.class.isAssignableFrom(type);
     }

 }

我们可以先看下第30行这个setProperties方法,发现有一个Properties参数传递进来,这个参数在哪儿传递的呢?就是在我们的mybatis-config.xml的第18行。

 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE configuration
   PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
   "http://mybatis.org/dtd/mybatis-3-config.dtd">

 <configuration>
 <!-- 注意configuration中各个属性配置的顺序应为:properties,settings,typeAliases,typeHandlers,objectFactory,objectWrapperFactory,reflectorFactory,plugins,environments,databaseIdProvider,mappers)-->
     <properties>
         <property name="driver" value="com.mysql.jdbc.Driver"/>
         <property name="url" value="jdbc:mysql://localhost:3306/test"/>
         <property name="username" value="root"/>
         <property name="password" value="0000"/>
     </properties>
     <typeHandlers>
         <typeHandler handler="day_8_mybatis.util.ExampleTypeHandler" javaType="java.util.Date" jdbcType="VARCHAR"/>
     </typeHandlers>
     <objectFactory type="day_8_mybatis.util.ExampleObjectFactory">
         <property name="someProperty" value="100"/>
     </objectFactory>
     <environments default="development">
         <environment id="development">
             <transactionManager type="JDBC" />
             <dataSource type="POOLED">
                 <property name="driver" value="${driver}"/>
                 <property name="url" value="${url}"/>
                 <property name="username" value="${username}"/>
                 <property name="password" value="${password}"/>
             </dataSource>
         </environment>
     </environments>
     <mappers>
         <mapper resource="day_8_mybatis/mapper/UserMapper.xml"/>
         <mapper resource="day_8_mybatis/mapper/NoteMapper.xml"/>
     </mappers>    

 </configuration>

选择性忽略14-16行的typeHandlers配置,那是在上一节将typeHandlers用到的配置。

我们就实现了这么个自定义对象工厂,在客户端代码中测试一下。

 package day_8_mybatis;

 import java.io.IOException;

 import org.apache.ibatis.session.SqlSession;

 import day_8_mybatis.util.SessionFactory;

 /**
  * 客户端
  * @author turbo
  *
  * 2016年9月11日
  */
 public class Main {

     /**
      * @param args
      * @throws IOException
      */
     public static void main(String[] args) throws Exception {
         String resource = "day_8_mybatis/mybatis-config.xml";        //获取mybatis配置文件路径
         SqlSession sqlSession = SessionFactory.getSqlSession(resource);    //通过SessionFactory工具类(此工具类为自己构造即util包中的SessionFactory)构造SqlSession

     }

 }

会发现控制台会有一个100的输出,那正是我们传递进去的参数。但似乎疑问在我们好像并没有调用任何方法啊,其实不然,mybatis的配置文件就是mybatis初始化首先要做的。我们在第22、23行做的工作就是加载configuration配置文件初始化mybatis,用于我们配置了ObjectFactory中的property当然实际上也就调用了ExampleObjectFactory中的setProperties。很多很多框架做的第一件事就是加载配置文件,根据配置初始化各种类各种服务,当然这也可以用代码来实现,不过框架的好处就是它已经为我们做了一些事情,使得我们仅仅需要通过一些配置就能实现我们想要的结果。那么至于create方法呢?我们可以上面说了对象工厂就是用来创建实例的,我们可以传递一个class类型的类,就可以通过对象工厂的create方法得到这个类的实例。

 package day_8_mybatis;

 import java.io.IOException;

 import org.apache.ibatis.session.SqlSession;

 import day_8_mybatis.pojo.People;
 import day_8_mybatis.util.ExampleObjectFactory;
 import day_8_mybatis.util.SessionFactory;

 /**
  * 客户端
  * @author turbo
  *
  * 2016年9月11日
  */
 public class Main {

     /**
      * @param args
      * @throws IOException
      */
     public static void main(String[] args) throws Exception {
         String resource = "day_8_mybatis/mybatis-config.xml";        //获取mybatis配置文件路径
         SqlSession sqlSession = SessionFactory.getSqlSession(resource);    //通过SessionFactory工具类(此工具类为自己构造即util包中的SessionFactory)构造SqlSession
         ExampleObjectFactory e = new ExampleObjectFactory();
         People p = (People) e.create(People.class);
         System.out.println(p.getName());
     }

 }

最后记住上面提到的MyBatis初始化过程就是解析配置文件创建Configuration对象的过程。这也会为我们在了解MyBatis之后学习其源码所要知道的一点。

相关文章