關於在MyBatis中的ObjectFactory有什么用,在官方文檔中有這樣的描述(大多數網上的博客都是直接引用這一描述):MyBatis 每次創建結果對象的新實例時,它都會使用一個對象工廠(ObjectFactory)實例來完成。 默認的對象工廠需要做的僅僅是實例化目標類,要么通過默認構造方法,要么在參數映射存在的時候通過參數構造方法來實例化。 如果想覆蓋對象工廠的默認行為,則可以通過創建自己的對象工廠來實現。對於像我這種水平的來說,完全就是一臉蒙逼,這到底有啥用?可以說這個對象工廠就是用來創建實體類的,MyBatis有一個DefaultObjectFactory默認對象工廠類,就像上面所說的默認的對象工廠需要做的僅僅是實例化目標類,要么通過默認構造方法,要么在參數映射存在的時候通過參數構造方法來實例化。它不做其他任何的處理。如果我們想在創建實例化一個目標類的時候做點啥其他的動作,可以繼承DefaultObjectFactory,覆寫父類方法,並在mybatis-config.xml中注冊配置這個對象工廠類。
自己實現一個對象工廠如下所示:
1 package day_8_mybatis.util; 2 3 import java.util.Collection; 4 import java.util.Iterator; 5 import java.util.Properties; 6 7 import org.apache.ibatis.reflection.factory.DefaultObjectFactory; 8 9 import day_8_mybatis.pojo.People; 10 11 /** 12 * @author turbo 13 * 14 * 2016年10月24日 15 */ 16 public class ExampleObjectFactory extends DefaultObjectFactory { 17 18 @Override 19 public Object create(Class type) { 20 if (type.equals(People.class)){ 21 People p = (People)super.create(type); 22 p.setAge(22); 23 p.setName("keven"); 24 return p; 25 } 26 return super.create(type); 27 } 28 29 @Override 30 public void setProperties(Properties properties) { 31 Iterator iterator = properties.keySet().iterator(); 32 while (iterator.hasNext()){ 33 String keyValue = String.valueOf(iterator.next()); 34 System.out.println(properties.getProperty(keyValue)); 35 } 36 super.setProperties(properties); 37 } 38 39 @Override 40 public <T> boolean isCollection(Class<T> type) { 41 return Collection.class.isAssignableFrom(type); 42 } 43 44 }
我們可以先看下第30行這個setProperties方法,發現有一個Properties參數傳遞進來,這個參數在哪兒傳遞的呢?就是在我們的mybatis-config.xml的第18行。
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE configuration 3 PUBLIC "-//mybatis.org//DTD Config 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-config.dtd"> 5 6 <configuration> 7 <!-- 注意configuration中各個屬性配置的順序應為:properties,settings,typeAliases,typeHandlers,objectFactory,objectWrapperFactory,reflectorFactory,plugins,environments,databaseIdProvider,mappers)--> 8 <properties> 9 <property name="driver" value="com.mysql.jdbc.Driver"/> 10 <property name="url" value="jdbc:mysql://localhost:3306/test"/> 11 <property name="username" value="root"/> 12 <property name="password" value="0000"/> 13 </properties> 14 <typeHandlers> 15 <typeHandler handler="day_8_mybatis.util.ExampleTypeHandler" javaType="java.util.Date" jdbcType="VARCHAR"/> 16 </typeHandlers> 17 <objectFactory type="day_8_mybatis.util.ExampleObjectFactory"> 18 <property name="someProperty" value="100"/> 19 </objectFactory> 20 <environments default="development"> 21 <environment id="development"> 22 <transactionManager type="JDBC" /> 23 <dataSource type="POOLED"> 24 <property name="driver" value="${driver}"/> 25 <property name="url" value="${url}"/> 26 <property name="username" value="${username}"/> 27 <property name="password" value="${password}"/> 28 </dataSource> 29 </environment> 30 </environments> 31 <mappers> 32 <mapper resource="day_8_mybatis/mapper/UserMapper.xml"/> 33 <mapper resource="day_8_mybatis/mapper/NoteMapper.xml"/> 34 </mappers> 35 36 </configuration> 37 38
選擇性忽略14-16行的typeHandlers配置,那是在上一節將typeHandlers用到的配置。
我們就實現了這么個自定義對象工廠,在客戶端代碼中測試一下。
1 package day_8_mybatis; 2 3 import java.io.IOException; 4 5 import org.apache.ibatis.session.SqlSession; 6 7 import day_8_mybatis.util.SessionFactory; 8 9 /** 10 * 客戶端 11 * @author turbo 12 * 13 * 2016年9月11日 14 */ 15 public class Main { 16 17 /** 18 * @param args 19 * @throws IOException 20 */ 21 public static void main(String[] args) throws Exception { 22 String resource = "day_8_mybatis/mybatis-config.xml"; //獲取mybatis配置文件路徑 23 SqlSession sqlSession = SessionFactory.getSqlSession(resource); //通過SessionFactory工具類(此工具類為自己構造即util包中的SessionFactory)構造SqlSession 24 25 } 26 27 }
會發現控制台會有一個100的輸出,那正是我們傳遞進去的參數。但似乎疑問在我們好像並沒有調用任何方法啊,其實不然,mybatis的配置文件就是mybatis初始化首先要做的。我們在第22、23行做的工作就是加載configuration配置文件初始化mybatis,用於我們配置了ObjectFactory中的property當然實際上也就調用了ExampleObjectFactory中的setProperties。很多很多框架做的第一件事就是加載配置文件,根據配置初始化各種類各種服務,當然這也可以用代碼來實現,不過框架的好處就是它已經為我們做了一些事情,使得我們僅僅需要通過一些配置就能實現我們想要的結果。那么至於create方法呢?我們可以上面說了對象工廠就是用來創建實例的,我們可以傳遞一個class類型的類,就可以通過對象工廠的create方法得到這個類的實例。
1 package day_8_mybatis; 2 3 import java.io.IOException; 4 5 import org.apache.ibatis.session.SqlSession; 6 7 import day_8_mybatis.pojo.People; 8 import day_8_mybatis.util.ExampleObjectFactory; 9 import day_8_mybatis.util.SessionFactory; 10 11 /** 12 * 客戶端 13 * @author turbo 14 * 15 * 2016年9月11日 16 */ 17 public class Main { 18 19 /** 20 * @param args 21 * @throws IOException 22 */ 23 public static void main(String[] args) throws Exception { 24 String resource = "day_8_mybatis/mybatis-config.xml"; //獲取mybatis配置文件路徑 25 SqlSession sqlSession = SessionFactory.getSqlSession(resource); //通過SessionFactory工具類(此工具類為自己構造即util包中的SessionFactory)構造SqlSession 26 ExampleObjectFactory e = new ExampleObjectFactory(); 27 People p = (People) e.create(People.class); 28 System.out.println(p.getName()); 29 } 30 31 }
最后記住上面提到的MyBatis初始化過程就是解析配置文件創建Configuration對象的過程。這也會為我們在了解MyBatis之后學習其源碼所要知道的一點。