mybaits source code analysis (6) basic support module-reflection-Io-type processing

    mybaits basic support

        Overview : The core processing work of mybaits is that the four modules of Executor, StatementHandler, ResultHandler, and paramHandler handle the entire SQL execution process. In these processes, some of the parameter-type objects of MapperStatement, SqlSource, ResultMap, and ParameterMapping are mainly processed for configuration analysis. Work, and finally generate the process of real SQL execution, and this article mainly explains some basic support modules to facilitate subsequent analysis.

        This article mainly analyzes three basic modules
        1, resource loading module
        2, reflection module
        3, type processing module

 1. Resource loading module

The resource loading module is under the io package, which is mainly composed of the Resources class and the ClassLoaderWrapper class. The ClassLoaderWrapper class provides methods for obtaining the class loader, as well as methods for loading resource files and classForName according to the class loader. Resources are the packaging of the ClassLoaderWrapper object. Provide a series of static call methods.


1. Part of the code of ClassLoaderWrapper

 /**
             * 获取类加载器列表: 指定的,当前线程的,当前类的,system类加载器
             */
            ClassLoader[] getClassLoaders(ClassLoader classLoader) {
                return new ClassLoader[] { classLoader, Thread.currentThread().getContextClassLoader(),
                        getClass().getClassLoader(), systemClassLoader };
            }
            
            ClassLoader systemClassLoader;
            
            {
                systemClassLoader = ClassLoader.getSystemClassLoader();
            }
            
            
            /**
             * classForName :取可用的classLoader调用Class.forName
             */
            Class<?> classForName(String name, ClassLoader[] classLoader) throws ClassNotFoundException {
                for (ClassLoader cl : classLoader) {
                    if (null != cl) {
                        try {
                            Class<?> c = Class.forName(name, true, cl);
                            if (null != c)
                                return c;
                        } catch (ClassNotFoundException e) {
                        }
                    }
                }
                throw new ClassNotFoundException("Cannot find class: " + name);
            }
            
            /**
             * getResourceAsStream :取可用的classLoader调用getResourceAsStream。
             */
            InputStream getResourceAsStream(String resource, ClassLoader[] classLoader) {
                for (ClassLoader cl : classLoader) {
                    if (null != cl) {
                        InputStream returnValue = cl.getResourceAsStream(resource);
                        if (null == returnValue)
                            returnValue = cl.getResourceAsStream("/" + resource);
                        if (null != returnValue)
                            return returnValue;
                    }
                }
                return null;
            }

    Second, the reflection module

Mybaits uses reflection in many places, and most of the external api calls the underlying reflection method by calling the MetaObject method. This class can wrap ordinary beans or collections, and it implements property identifiers to access properties. In addition, the Reflector class is used by the reflection module to call the native reflection method, and it is also a class for the underlying functional operation of MetaObject.

1. MetaObject test case

@Test
	public void test1(){
		Person p = new Person();
		MetaObject meta = MetaObject.forObject(p, new DefaultObjectFactory(), new DefaultObjectWrapperFactory());
		meta.setValue("name", "haha"); // setValue通过反射设置对象的属性
		System.out.println(p.getName());
	}
	
	@Test
	public void test2(){
		Person p = new Person();
		p.setName("haha");
		List<Person> ps = new ArrayList<Person>(); // 包装lists
		MetaObject meta = MetaObject.forObject(ps, new DefaultObjectFactory(), new DefaultObjectWrapperFactory());
		meta.add(p); // MetaObject传入参数如果是集合类型,可以通过add给集合添加属性。
		System.out.println(ps.get(0).getName());
	}
	
	@Test
	public void test3(){
		Person p = new Person();
		p.setName("haha");
		Map<String,Person> map = new HashMap<String,Person>(); // 包装map
		MetaObject meta = MetaObject.forObject(map, new DefaultObjectFactory(), new DefaultObjectWrapperFactory());
		meta.setValue("deer", p); // 通过setValue可以给map添加属性
		System.out.println(map.get("deer").getName());
	}
	
	/**
	 * 属性分割符,操作内部成员对象的属性
	 */
	@Test
	public void test4(){
		Person p = new Person();
		MetaObject meta = MetaObject.forObject(p, new DefaultObjectFactory(), new DefaultObjectWrapperFactory());
		meta.setValue("child.name", "haha"); // 可以通过.的方式调用属性的属性
		System.out.println(p.getChild().getName()); // 普通方式获取
		System.out.println(meta.getValue("child.name")); // 反射方式获取值,也可以用.的方式
	}

	/**
	 * 属性分割符,操作内部成员集合对象的属性
	 */
	@Test
	public void test5(){
		Person p = new Person();
		p.getChildren().add(new Person());
		MetaObject meta = MetaObject.forObject(p, new DefaultObjectFactory(), new DefaultObjectWrapperFactory());
		meta.setValue("children[0].name", "haha");
		System.out.println(p.getChildren().get(0).getName());
		System.out.println(meta.getValue("children[0].name"));
	}

From the above test, we can see that MetaObject can be very convenient to use. It requires reflection operations such as property manipulation, method invocation, instance creation, etc., and it is compatible with the use of collections or ordinary beans.

    2. Class of reflection module

    MetaObject : Mainly used externally, the functions have been demonstrated above.
    Reflector : The basic reflection class, which wraps all the methods, files, Constructor, etc. reflection methods of a class, and parses them all during initialization.
    MetaClass : wraps the reflection function, and enhances the support for property analysis, that is, the form of prop.prop.prop.
    PropertyTokenizer : A wrapper for the property structure in the form of prop.prop.prop.
    ObjectWrapper : Object wrapper interface, which is created by MetaObject and holds a reference to MetaObject (used for class recursive calls). There are 4 implementations, one is BaseWrapper, one is BeanWrapper, one is CollectionWrapper, and the other is MapWrapper.

    3、Reflector

a) First look at the main properties and constructor

 private Class<?> type;
	  private String[] readablePropertyNames = EMPTY_STRING_ARRAY; // 可读属性名数组
	  private String[] writeablePropertyNames = EMPTY_STRING_ARRAY; // 可写属性名数组
	  private Map<String, Invoker> setMethods = new HashMap<String, Invoker>(); // set方法
	  private Map<String, Invoker> getMethods = new HashMap<String, Invoker>(); // get方法
	  private Map<String, Class<?>> setTypes = new HashMap<String, Class<?>>(); // set类型
	  private Map<String, Class<?>> getTypes = new HashMap<String, Class<?>>(); // get类型
	  private Constructor<?> defaultConstructor; // 默认构造函数
	  private Reflector(Class<?> clazz) {
	    type = clazz; // 指定类型
	    addDefaultConstructor(clazz); //解析默认构造函数
	    addGetMethods(clazz); // 解析所有get方法
	    addSetMethods(clazz); // 解析所有set方法
	    addFields(clazz); // 所有字段
	    readablePropertyNames = getMethods.keySet().toArray(new String[getMethods.keySet().size()]); // 可读属性名的集合
	    writeablePropertyNames = setMethods.keySet().toArray(new String[setMethods.keySet().size()]); // 可写属性名的集合
	  }

      When Reflector creates the constructor, it parses all the methods, fields, constructors and other information of the class, which can be used directly or for judgment later. Let's look at the process of parsing an adding method.
  b) addGetMethods method

 private void addGetMethods(Class<?> cls) {
	    Map<String, List<Method>> conflictingGetters = new HashMap<String, List<Method>>(); // 用于解决多个method冲突用
	    Method[] methods = getClassMethods(cls); // 得到本类父类的所有声明方法,踢出了桥接方法
	    for (Method method : methods) {
	      String name = method.getName();
	      if (name.startsWith("get") && name.length() > 3) { // 是get方法
		if (method.getParameterTypes().length == 0) { // 并且没有参数
		  name = PropertyNamer.methodToProperty(name); // 方法名称变成属性名
		  addMethodConflict(conflictingGetters, name, method); // 添加到处理冲突的map中,因为一个属性名可能对应多个方法
		}
	      } else if (name.startsWith("is") && name.length() > 2) { // 是is方法
		if (method.getParameterTypes().length == 0) {
		  name = PropertyNamer.methodToProperty(name);
		  addMethodConflict(conflictingGetters, name, method);
		}
	      }
	    }
	    resolveGetterConflicts(conflictingGetters); // 处理冲突
	  }
		 
    	   private void resolveGetterConflicts(Map<String, List<Method>> conflictingGetters) {
	    for (String propName : conflictingGetters.keySet()) {
	      List<Method> getters = conflictingGetters.get(propName);
	      Iterator<Method> iterator = getters.iterator();
	      Method firstMethod = iterator.next();
	      if (getters.size() == 1) { // 冲突只有1个method直接添加
		addGetMethod(propName, firstMethod);
	      } else {
		Method getter = firstMethod; 
		Class<?> getterType = firstMethod.getReturnType(); // 上次遍历方法的返回类型
		while (iterator.hasNext()) {
		  Method method = iterator.next();
		  Class<?> methodType = method.getReturnType();
		  if (methodType.equals(getterType)) {
		    throw new ReflectionException(""); // 虽然是合法重载,但是属性类型不明确,不符合规范。
		  } else if (methodType.isAssignableFrom(getterType)) { // 返回类型是上次的父类型,更不明确,不使用。
		    // OK getter type is descendant
		  } else if (getterType.isAssignableFrom(methodType)) { // 如果当前遍历方法返回类型比上次返回类型更具体。
		    getter = method; // 指定此方法为当前遍历方法
		    getterType = methodType;  // 指定成此类型
		  } else {
		    throw new ReflectionException();
		  }
		}
		addGetMethod(propName, getter);
	      }
	    }
	  }

4、MetaClass

 MetaClass is a wrapper of Reflector, and enhanced reflection support for prop.prop property accessors.

5、 PropertyTokenizer

     The main function of PropertyTokenizer is to represent a prop.prop property symbol form as an object, for
     example: list[0].item[2].id finally resolves to TempObj [name=list, IndexedName=list[0], index=0, children The object
     code of =item[2].id] is implemented as follows:

 public PropertyTokenizer(String fullname) {
		    int delim = fullname.indexOf('.'); // 对象符
		    if (delim > -1) { // 有
		      name = fullname.substring(0, delim); // name第一节点
		      children = fullname.substring(delim + 1); // children为剩余的
		    } else {
		      name = fullname; 
		      children = null;
		    }
		    indexedName = name; // 属性名称有可能带[]的形式
		    delim = name.indexOf('[');
		    if (delim > -1) { // 如果有[
		      index = name.substring(delim + 1, name.length() - 1); // index为数组属性中角标
		      name = name.substring(0, delim); // name要去除[]
		    }
		  }

6、MetaObject

 a) First look at the constructor of MetaObject

private Object originalObject;  // 原对象
	  private ObjectWrapper objectWrapper; // 对象包装
	  private ObjectFactory objectFactory; // 对象创建工厂
	  private ObjectWrapperFactory objectWrapperFactory; // 忽略
	  private MetaObject(Object object, ObjectFactory objectFactory, ObjectWrapperFactory objectWrapperFactory) {
	    this.originalObject = object;
	    this.objectFactory = objectFactory;
	    this.objectWrapperFactory = objectWrapperFactory;
	    if (object instanceof ObjectWrapper) {
	      this.objectWrapper = (ObjectWrapper) object;
	    } else if (objectWrapperFactory.hasWrapperFor(object)) { // 空实现
	      this.objectWrapper = objectWrapperFactory.getWrapperFor(this, object);
	    } else if (object instanceof Map) { // MapWrapper的包装
	      this.objectWrapper = new MapWrapper(this, (Map) object);
	    } else if (object instanceof Collection) { // Collection的包装
	      this.objectWrapper = new CollectionWrapper(this, (Collection) object);
	    } else {  // bean的包装
	      this.objectWrapper = new BeanWrapper(this, object); // 如果是javabean,就包装成这个,并且传递this,是为了伪递归调用本对象的getValue等方法。
	    }
	  }

As can be seen from the constructor of MetaObject, MetaObject will create corresponding ObjectWrapper according to the type of object to be wrapped. MapWrapper and CollectionWrapper are the implementation of some container methods, and BeanWrapper is the implementation of reflection methods. Each BeanWrapper holds a reference to the MetaObject that created it, and internally calls MetaClass to implement reflection operations.

     We analyze the following setValue method .

  public void setValue(String name, Object value) {
		    PropertyTokenizer prop = new PropertyTokenizer(name); // 包装属性访问符成为对象
		    if (prop.hasNext()) { // 判断是否有子属性
			// 这里反射获取此子属性的值,这里内部调用getValue,但是只有单个name,因此不会递归获取子属性
			// 获取子属性后,会包装成新的MetaObject
		        MetaObject metaValue = metaObjectForProperty(prop.getIndexedName()); 
			if (metaValue == SystemMetaObject.NULL_META_OBJECT) { // value空值包装成的默认空的MetaObject
		            if (value == null && prop.getChildren() != null) {
		              return; 
		            } else {
			      // 实例化此子属性,并且反射设置到此对象中,另外包装成MetaObject
		             metaValue = objectWrapper.instantiatePropertyValue(name, prop, objectFactory);
		            } 
			}
			// 当前name属性因为有子属性需要设置,本name的属性已经实例化,并且本name属性也已经包装成了MetaValue,就可以伪递归SetValue
		        metaValue.setValue(prop.getChildren(), value);
		    } else { // 只设置一级属性的值。
		      objectWrapper.set(prop, value);
		    }
		  }
		  public MetaObject metaObjectForProperty(String name) {
		    Object value = getValue(name); // 因为name是个单节点的属性,getValue不会递归了。
		    return MetaObject.forObject(value, objectFactory, objectWrapperFactory); // value就算空值也会进行包装
		  }

The above is the way to set the object symbol form attribute string through MetaObject reflection. The function of this class integrates the functions of all the above classes.
      MetaObject implementation logic text description:
        an object may be a collection or a javaBean. If we want to access it through the attribute symbol, we first object the attribute symbol, and then instantiate different ObjectWrappers according to whether the object is a collection or a javabean. ObjectWrapper is responsible for reflection Or access properties in a collection, multi-level properties, and perform pseudo-recursive operations by packaging each level into a new MetaObject. The props passed in recursively are after the second level.

 

Three, type processing module

 1. Basic introduction.

  The top-level interface for type handling is TypeHandler, and its interface form is as follows:

  类型处理的顶级接口是TypeHandler,它的接口形式如下:
	  public interface TypeHandler<T> {
		
		/**
		 * 填充PreparedStatement的参数
		 */
		void setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException;
	
		/**
		 * 得到结果,根据别名
		 */
		T getResult(ResultSet rs, String columnName) throws SQLException;
	
		/**
		 * 得到结果,根据列角标
		 */
		T getResult(ResultSet rs, int columnIndex) throws SQLException;
	
		/**
		 * 从CallableStatement得到结果。
		 */
		T getResult(CallableStatement cs, int columnIndex) throws SQLException;
	
	}

 Its main function is for ParameterHandler and ResultetHandler to process the parameter implicit of the prepared statement, and the type conversion method of the result set processing. And its specific realization is the realization of different processing for each type. Let's pick a few and take a look.

public class IntegerTypeHandler extends BaseTypeHandler<Integer> {
	  @Override
	  public void setNonNullParameter(PreparedStatement ps, int i, Integer parameter, JdbcType jdbcType)
	      throws SQLException {
	    ps.setInt(i, parameter);
	  }
	  @Override
	  public Integer getNullableResult(ResultSet rs, String columnName)
	      throws SQLException {
	    return rs.getInt(columnName);
	  }
	  @Override
	  public Integer getNullableResult(ResultSet rs, int columnIndex)
	      throws SQLException {
	    return rs.getInt(columnIndex);
	  }
	  @Override
	  public Integer getNullableResult(CallableStatement cs, int columnIndex)
	      throws SQLException {
	    return cs.getInt(columnIndex);
	  }
	}

As you can see from the above, the implementation of each type of type processing is relatively simple. The key is, why use this type of processor, such as parameter mapping, which type of processor do we need? This is to find the type processor according to the actual type of the parameter. Similarly, the return value processing can be based on the return value type or the type configuration of the resultMap to find the specific type processor. The specific process is not checked, we only look at the type How is the processor registered and where is it registered?

2. Registration of
TypeHandler TypeHandler is registered in the TypeHandlerRegistry instance in Configurn.

Properties of TypeHandlerRegistry

      
        // JDBCType对应的处理器映射
        private final Map<JdbcType, TypeHandler<?>> JDBC_TYPE_HANDLER_MAP = new EnumMap<JdbcType, TypeHandler<?>>(JdbcType.class);
        // java类型对应的处理器映射 (一个java类型可以注册多个jdbc类型,默认null的key注册的是默认的处理器)
        private final Map<Type, Map<JdbcType, TypeHandler<?>>> TYPE_HANDLER_MAP = new HashMap<Type, Map<JdbcType, TypeHandler<?>>>();
        // 类型处理器clas和实例的映射
        private final Map<Class<?>, TypeHandler<?>> ALL_TYPE_HANDLERS_MAP = new HashMap<Class<?>, TypeHandler<?>>();

Actual registration method

 private void register(Type javaType, JdbcType jdbcType, TypeHandler<?> handler) {
	    if (javaType != null) { 
	      Map<JdbcType, TypeHandler<?>> map = TYPE_HANDLER_MAP.get(javaType);
	      if (map == null) { // 创建子map
	        map = new HashMap<JdbcType, TypeHandler<?>>();
	        TYPE_HANDLER_MAP.put(javaType, map);
	      }
	      map.put(jdbcType, handler); // put进子map
	      if (reversePrimitiveMap.containsKey(javaType)) { // 同时注册元素类型
	        register(reversePrimitiveMap.get(javaType), jdbcType, handler);
	      }
	    } 
	    ALL_TYPE_HANDLERS_MAP.put(handler.getClass(), handler);
	  }

3. The actual use of mybaits type processors.

 

END!

 

 

 

 

 

 

 

 

 

Guess you like

Origin blog.csdn.net/shuixiou1/article/details/113705958