在 config.xml 当中有一个节点是 ObjectFactory 和 ObjectWrapperFactory:
<objectFactory type=""> <property name="" value=""/> </objectFactory> <objectWrapperFactory type=""> <property name="" value=""/> </objectWrapperFactory>
MyBatis 每次创建结果对象的新实例时,它都会使用一个对象工厂(ObjectFactory)实例来完成。 默认的对象工厂需要做的仅仅是实例化目标类,要么通过默认构造方法,要么在参数映射存在的时候通过参数构造方法来实例化。
ObjectFactory 接口很简单,它包含两个创建用的方法,一个是处理默认构造方法的,另外一个是处理带参数的构造方法的。 最后,setProperties 方法可以被用来配置 ObjectFactory,在初始化你的 ObjectFactory 实例后, objectFactory 元素体中定义的属性会被传递给 setProperties 方法。
public interface ObjectFactory { void setProperties(Properties properties); <T> T create(Class<T> type); <T> T create(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs); <T> boolean isCollection(Class<T> type); }
一般不会自己创建 ObjectFactory,都会使用默认的 DefaultObjectFactory:
public class DefaultObjectFactory implements ObjectFactory, Serializable { private static final long serialVersionUID = -8855120656740914948L; @Override public <T> T create(Class<T> type) { return create(type, null, null); } @SuppressWarnings("unchecked") @Override public <T> T create(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> 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> T instantiateClass(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) { try { Constructor<T> constructor; if (constructorArgTypes == null || constructorArgs == null) { constructor = type.getDeclaredConstructor(); if (!constructor.isAccessible()) { constructor.setAccessible(true); } return constructor.newInstance(); } constructor = type.getDeclaredConstructor(constructorArgTypes.toArray(new Class[constructorArgTypes.size()])); if (!constructor.isAccessible()) { constructor.setAccessible(true); } return constructor.newInstance(constructorArgs.toArray(new Object[constructorArgs.size()])); } catch (Exception e) { StringBuilder argTypes = new StringBuilder(); if (constructorArgTypes != null && !constructorArgTypes.isEmpty()) { for (Class<?> argType : constructorArgTypes) { argTypes.append(argType.getSimpleName()); argTypes.append(","); } argTypes.deleteCharAt(argTypes.length() - 1); // remove trailing , } StringBuilder argValues = new StringBuilder(); if (constructorArgs != null && !constructorArgs.isEmpty()) { for (Object argValue : constructorArgs) { argValues.append(String.valueOf(argValue)); argValues.append(","); } argValues.deleteCharAt(argValues.length() - 1); // remove trailing , } throw new ReflectionException("Error instantiating " + type + " with invalid types (" + argTypes + ") or values (" + argValues + "). Cause: " + e, e); } } 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 <T> boolean isCollection(Class<T> type) { return Collection.class.isAssignableFrom(type); } }
实现比较简单,先是通过 resolveInterface 来解析传递进来的 Class 类型,然后基于反射创建对象实例。
在上一篇分析当中,ParameterMappingTokenHandler 当中有一个属性 MetaObject 还没有分析,并且当中的 buildParameterMapping 方法也还没仔细分析,下面仔细分析这些内容。
MetaObject
ParameterMappingTokenHandler 的构造方法如下创建 MetaObject:
public ParameterMappingTokenHandler(Configuration configuration, Class<?> parameterType, Map<String, Object> additionalParameters) { super(configuration); this.parameterType = parameterType; this.metaParameters = configuration.newMetaObject(additionalParameters); } //Configuration 当中的方法 public MetaObject newMetaObject(Object object) { return MetaObject.forObject(object, objectFactory, objectWrapperFactory, reflectorFactory); } //MetaObject 当中的方法 public static MetaObject forObject(Object object, ObjectFactory objectFactory, ObjectWrapperFactory objectWrapperFactory, ReflectorFactory reflectorFactory) { if (object == null) { return SystemMetaObject.NULL_META_OBJECT; } else { return new MetaObject(object, objectFactory, objectWrapperFactory, reflectorFactory); } }
在 ParameterMappingTokenHandler 当中是通过 configuration 来创建的 MetaObject,而内部是通过 MetaObject 的静态方法来创建 MetaObject 的实例。那么继续看一下 MetaObject 里面的属性,以及构造方法:
private Object originalObject; private ObjectWrapper objectWrapper; private ObjectFactory objectFactory; private ObjectWrapperFactory objectWrapperFactory; private ReflectorFactory reflectorFactory; private MetaObject(Object object, ObjectFactory objectFactory, ObjectWrapperFactory objectWrapperFactory, ReflectorFactory reflectorFactory) { this.originalObject = object; this.objectFactory = objectFactory; this.objectWrapperFactory = objectWrapperFactory; this.reflectorFactory = reflectorFactory; if (object instanceof ObjectWrapper) { this.objectWrapper = (ObjectWrapper) object; } else if (objectWrapperFactory.hasWrapperFor(object)) { this.objectWrapper = objectWrapperFactory.getWrapperFor(this, object); } else if (object instanceof Map) { this.objectWrapper = new MapWrapper(this, (Map) object); } else if (object instanceof Collection) { this.objectWrapper = new CollectionWrapper(this, (Collection) object); } else { this.objectWrapper = new BeanWrapper(this, object); } }
简单解释下传递进来的参数,第一个 object 就是我们在进行执行 sql 的时候传递进来的参数类型,有几种情况,一种的 map,一种是实体 bean,或者是 Collection 等。
里面有一个参数是 ObjectWrapper ,在构造方法当中会判断 object 的类型来创建 ObjectWrapper 的实例。
继续来看 ParameterMappingTokenHandler.buildParameterMapping 方法当中,有一段代码是:
String property = propertiesMap.get("property"); Class<?> propertyType; if (metaParameters.hasGetter(property)) //通过 property 来获取 property 的类型,property 可以是 OGNL 表达式的字符串,例如: // user.address.name 、 user[addressStr] 这样的
来看 MetaObject 的 hasGetter 方法:
public boolean hasGetter(String name) { return objectWrapper.hasGetter(name); } //假设我们传递进来的是参数是实体 bean,那么 objectWrapper 就是 BeanWrapper 对象 //BeanWrapper 当中的 hasGetter 方法 public boolean hasGetter(String name) { PropertyTokenizer prop = new PropertyTokenizer(name); if (prop.hasNext()) { if (metaClass.hasGetter(prop.getIndexedName())) { MetaObject metaValue = metaObject.metaObjectForProperty(prop.getIndexedName()); if (metaValue == SystemMetaObject.NULL_META_OBJECT) { return metaClass.hasGetter(name); } else { return metaValue.hasGetter(prop.getChildren()); } } else { return false; } } else { return metaClass.hasGetter(name); } }
先来看下 BeanWrapper 的构造方法:
public class BeanWrapper extends BaseWrapper { private Object object; private MetaClass metaClass; public BeanWrapper(MetaObject metaObject, Object object) { super(metaObject); this.object = object; this.metaClass = MetaClass.forClass(object.getClass(), metaObject.getReflectorFactory()); } }
MetaClass 先不分析,后续进行分析。
在看 BeanWrapper.hasGetter 方法,第一行就是创建 PropertyTokenizer 对象。
简单描述下 PropertyTokenizer 类就是用来解析 OGNL 表达式的情况的。
public class PropertyTokenizer implements Iterable<PropertyTokenizer>, Iterator<PropertyTokenizer> { private String name; private String indexedName; private String index; private String children; public PropertyTokenizer(String fullname) { int delim = fullname.indexOf('.'); if (delim > -1) { name = fullname.substring(0, delim); children = fullname.substring(delim + 1); } else { name = fullname; children = null; } indexedName = name; delim = name.indexOf('['); if (delim > -1) { index = name.substring(delim + 1, name.length() - 1); name = name.substring(0, delim); } }
以两个例子来看下构造方法初始化的过程:
//参数 user.address.name //结果 name = user,children = address.name,indexedName = user,index = null //参数 user[addressStr] //结果 name = user,children = null,indexedName = user[addressStr],index = addressStr
继续看 BeanWrapper.hasGetter 方法,下面的调用过程:
public boolean hasGetter(String name) { PropertyTokenizer prop = new PropertyTokenizer(name); if (prop.hasNext()) { if (metaClass.hasGetter(prop.getIndexedName())) { MetaObject metaValue = metaObject.metaObjectForProperty(prop.getIndexedName()); if (metaValue == SystemMetaObject.NULL_META_OBJECT) { return metaClass.hasGetter(name); } else { return metaValue.hasGetter(prop.getChildren()); } } else { return false; } } else { return metaClass.hasGetter(name); } } //PropertyTokenizer 当中的方法 @Override public boolean hasNext() { return children != null; }
根据第一个例子的情况,参数 user.address.name, hasNext() 返回 true,因为 children = address.name,所以进入 if 语句后又会执行:
if (metaClass.hasGetter(prop.getIndexedName())) //PropertyTokenizer 当中的方法 public String getIndexedName() { return indexedName;//参数是 user.address.name 的时候 indexedName = user } //MetaClass 当中的方法 public boolean hasGetter(String name) {//此时 name 的值是 user PropertyTokenizer prop = new PropertyTokenizer(name); if (prop.hasNext()) {//此时返回的是 false if (reflector.hasGetter(prop.getName())) { MetaClass metaProp = metaClassForProperty(prop); return metaProp.hasGetter(prop.getChildren()); } else { return false; } } else { return reflector.hasGetter(prop.getName());//反射获取对应的 user 对象 } }
然后继续执行:
MetaObject metaValue = metaObject.metaObjectForProperty(prop.getIndexedName()); if (metaValue == SystemMetaObject.NULL_META_OBJECT) { return metaClass.hasGetter(name); } else { return metaValue.hasGetter(prop.getChildren()); }
执行过程不深入跟踪,就是获取到 user 的对象,然后在包装成 MetaObject 对象,然后继续调用 hasGetter 方法,并且传递进去 childeren 就是 address.name 参数,递归形式的进行解析。
所以在 ParameterMappingTokenHandler 当中的 buildParameterMapping 方法里面就这样获取到了 propertyType 的类型。
MetaClass
在 BeanWrapper 当中有个属性是 MetaClass 的对象,我们来分析下 MetaClass。
在 BeanWrapper 的构造方法当中如下创建 MetaClass 实例:
this.metaClass = MetaClass.forClass(object.getClass(), metaObject.getReflectorFactory()); public class MetaClass { private ReflectorFactory reflectorFactory; private Reflector reflector; private MetaClass(Class<?> type, ReflectorFactory reflectorFactory) { this.reflectorFactory = reflectorFactory; this.reflector = reflectorFactory.findForClass(type); } public static MetaClass forClass(Class<?> type, ReflectorFactory reflectorFactory) { return new MetaClass(type, reflectorFactory); }
metaObject 当中的 getReflectorFactory 就是 Configuration 当中的 reflectorFactory,来看下 ReflectorFactory 接口的内容,以及默认实现:
public interface ReflectorFactory { boolean isClassCacheEnabled();//是否 Class 可以缓存 void setClassCacheEnabled(boolean classCacheEnabled);//设置 Class 是否可以缓存 Reflector findForClass(Class<?> type);// 根据 Class 查找 Reflector } public class DefaultReflectorFactory implements ReflectorFactory { private boolean classCacheEnabled = true; private final ConcurrentMap<Class<?>, Reflector> reflectorMap = new ConcurrentHashMap<Class<?>, Reflector>(); public DefaultReflectorFactory() { } @Override public boolean isClassCacheEnabled() { return classCacheEnabled; } @Override public void setClassCacheEnabled(boolean classCacheEnabled) { this.classCacheEnabled = classCacheEnabled; } @Override public Reflector findForClass(Class<?> type) { if (classCacheEnabled) { // synchronized (type) removed see issue #461 Reflector cached = reflectorMap.get(type); if (cached == null) { cached = new Reflector(type); reflectorMap.put(type, cached); } return cached; } else { return new Reflector(type); } } }
默认实现也比较简单,就是里面添加了个 ConcurrentMap ,不多解释。
MetaClass 里面还有一个属性是 Reflector,这个也是 ReflectorFactory 获取的类型。
public class Reflector { private static final String[] EMPTY_STRING_ARRAY = new String[0]; private Class<?> type; private String[] readablePropertyNames = EMPTY_STRING_ARRAY; private String[] writeablePropertyNames = EMPTY_STRING_ARRAY; private Map<String, Invoker> setMethods = new HashMap<String, Invoker>(); private Map<String, Invoker> getMethods = new HashMap<String, Invoker>(); private Map<String, Class<?>> setTypes = new HashMap<String, Class<?>>(); private Map<String, Class<?>> getTypes = new HashMap<String, Class<?>>(); private Constructor<?> defaultConstructor; private Map<String, String> caseInsensitivePropertyMap = new HashMap<String, String>(); public Reflector(Class<?> clazz) { type = clazz; addDefaultConstructor(clazz);//添加默认的无参数的构造方法 addGetMethods(clazz);//所有 get 方法添加到 map addSetMethods(clazz);//所有 set 方法添加到 map addFields(clazz);//所有属性 readablePropertyNames = getMethods.keySet().toArray(new String[getMethods.keySet().size()]); writeablePropertyNames = setMethods.keySet().toArray(new String[setMethods.keySet().size()]); for (String propName : readablePropertyNames) { caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName); } for (String propName : writeablePropertyNames) { caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName); } } // 省略代码.. }
从属性以及构造方法当中调用的一些方法可以看出来了,这个类就是用来简化反射操作的一个工具类。不仔细研究了。
下篇继续分析 mybatis 的其他内容。
—EOF—