public Configuration parse() { if (parsed) { thrownewBuilderException("Each XMLConfigBuilder can only be used once."); } parsed = true; //这里从DOM树中取出相应元素的属性值,初始化configuration parseConfiguration(parser.evalNode("/configuration"));
//返回Configuration的对象 return configuration; }
privatevoidparseConfiguration(XNode root) { try { //issue #117 read properties first propertiesElement(root.evalNode("properties")); Propertiessettings= settingsAsProperties(root.evalNode("settings")); loadCustomVfs(settings); typeAliasesElement(root.evalNode("typeAliases")); pluginElement(root.evalNode("plugins")); objectFactoryElement(root.evalNode("objectFactory")); objectWrapperFactoryElement(root.evalNode("objectWrapperFactory")); reflectorFactoryElement(root.evalNode("reflectorFactory")); settingsElement(settings); //read it after objectFactory and objectWrapperFactory issue #631 environmentsElement(root.evalNode("environments")); databaseIdProviderElement(root.evalNode("databaseIdProvider")); typeHandlerElement(root.evalNode("typeHandlers")); mapperElement(root.evalNode("mappers")); } catch (Exception e) { thrownewBuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e); } }
privatevoidbindMapperForNamespace() { //获取刚才读入的命名空间的配置信息 Stringnamespace= builderAssistant.getCurrentNamespace(); if (namespace != null) { Class<?> boundType = null; try { //首先,尝试根据命名空间找到对应的Class对象 boundType = Resources.classForName(namespace); } catch (ClassNotFoundException e) { //ignore, bound type is not required }
//根据命名空间成功找到Class对象 if (boundType != null) { if (!configuration.hasMapper(boundType)) { //Spring may not know the real resource name so we set a flag //to prevent loading again this resource from the mapper interface //look at MapperAnnotationBuilder#loadXmlResource configuration.addLoadedResource("namespace:" + namespace);
public <T> voidaddMapper(Class<T> type) { //只有当type是接口时,才会对其进行管理 if (type.isInterface()) { if (hasMapper(type)) { thrownewBindingException("Type " + type + " is already known to the MapperRegistry."); } booleanloadCompleted=false; try { //添加一个<Class<?>, MapperProxyFactory<?>>的键值对,其中MapperProxyFactory是代理工厂类,为Mapper指定接口创建代理类 knownMappers.put(type, newMapperProxyFactory<T>(type)); //It's important that the type is added before the parser is run //otherwise the binding may automatically be attempted by the //mapper parser. If the type is already known, it won't try. //如果该接口配置了相关注解(@Select之类的SQL注解),那么进行扫描解析 MapperAnnotationBuilderparser=newMapperAnnotationBuilder(config, type); parser.parse(); loadCompleted = true; } finally { if (!loadCompleted) { knownMappers.remove(type); } } } }
public <T> T getMapper(Class<T> type, SqlSession sqlSession) { //首先从缓存中,依据Class对象获取到MapperProxyFactory的实例 final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type); //如果获取不到MapperProxyFactory的实例,那么意味着映射器namespace并未对应着一个Java接口,之前我们分析过,因此无法用Mapper方式来进行SQL操作,这里直接抛异常 if (mapperProxyFactory == null) { thrownewBindingException("Type " + type + " is not known to the MapperRegistry."); } try { //通过代理工厂类为当前Java接口创建代理对象,这是核心 return mapperProxyFactory.newInstance(sqlSession); } catch (Exception e) { thrownewBindingException("Error getting mapper instance. Cause: " + e, e); } }
接下来,我们看下这个MapperProxyFactory是如何为我们创建代理对象的
1 2 3 4 5 6 7 8 9 10
public T newInstance(SqlSession sqlSession) { //这个MapperProxy实现了InvocationHandler,即JDK动态代理的核心接口 final MapperProxy<T> mapperProxy = newMapperProxy<T>(sqlSession, mapperInterface, methodCache); return newInstance(mapperProxy); }
/** * <p> * The key is the index and the value is the name of the parameter.<br /> * The name is obtained from {@link Param} if specified. When {@link Param} is not specified, * the parameter index is used. Note that this index could be different from the actual index * when the method has special parameters (i.e. {@link RowBounds} or {@link ResultHandler}). * </p> * <ul> * <li>aMethod(@Param("M") int a, @Param("N") int b) -> {{0, "M"}, {1, "N"}}</li> * <li>aMethod(int a, int b) -> {{0, "0"}, {1, "1"}}</li> * <li>aMethod(int a, RowBounds rb, int b) -> {{0, "0"}, {2, "1"}}</li> * </ul> */ //该字段用于存放参数键值对,key为参数在参数列表中的位置,value为参数名(如果有@Param修饰,那就是@Param修饰的名字;否则就是"0"、"1"、"2"这样的字符串) privatefinal SortedMap<Integer, String> names;
privateboolean hasParamAnnotation;
publicParamNameResolver(Configuration config, Method method) { final Class<?>[] paramTypes = method.getParameterTypes(); final Annotation[][] paramAnnotations = method.getParameterAnnotations(); final SortedMap<Integer, String> map = newTreeMap<Integer, String>(); intparamCount= paramAnnotations.length; //get names from @Param annotations for (intparamIndex=0; paramIndex < paramCount; paramIndex++) { if (isSpecialParameter(paramTypes[paramIndex])) { //skip special parameters continue; } Stringname=null;
//查看当前参数是否被@Param注解修饰 for (Annotation annotation : paramAnnotations[paramIndex]) { if (annotation instanceof Param) { hasParamAnnotation = true; //如果当前参数被@Param注解修饰,那么名字为@Param注解设定的名字 name = ((Param) annotation).value(); break; } } //如果当前参数没有被@Param注解修饰 if (name == null) { //@Param was not specified. //这里尝试从Method对象获取参数名字,一般通过反射获取到的参数名字是arg0,arg1,arg2等等 if (config.isUseActualParamName()) { name = getActualParamName(method, paramIndex); }
//用"0","1","2"作为参数的名字 if (name == null) { //use the parameter index as the name ("0", "1", ...) //gcode issue #71 name = String.valueOf(map.size()); } } map.put(paramIndex, name); } names = Collections.unmodifiableSortedMap(map); }
//通过反射获取参数的名字,一般而言,参数名字是arg0,arg1,arg2等等 private String getActualParamName(Method method, int paramIndex) { if (Jdk.parameterExists) { return ParamNameUtil.getParamNames(method).get(paramIndex); } returnnull; }
/** * Returns parameter names referenced by SQL providers. */ public String[] getNames() { return names.values().toArray(newString[0]); }
/** * <p> * A single non-special parameter is returned without a name.<br /> * Multiple parameters are named using the naming rule.<br /> * In addition to the default names, this method also adds the generic names (param1, param2, * ...). * </p> */ //进行参数解析以及封装的核心方法 public Object getNamedParams(Object[] args) { finalintparamCount= names.size(); if (args == null || paramCount == 0) { returnnull; } //如果参数没有@Param标记,且参数只有1个 elseif (!hasParamAnnotation && paramCount == 1) { //直接透传,不进行封装 return args[names.firstKey()]; } //参数多余一个,或者参数被@Param标记 else { //将参数封装成一个Map final Map<String, Object> param = newMapperMethod.ParamMap<Object>(); inti=0; for (Map.Entry<Integer, String> entry : names.entrySet()) { //对于有@Param修饰的参数而言,键值就是@Param注解的值 //对于没有@Param修饰的参数而言,键值一般就是"argi",其中i是当前参数在参数列表中的位置,i从0计算 //极少情况下,键值是"0","1","2"...。产生这种键值的原因是没有@Param注解修饰,且通过反射拿不到参数名 param.put(entry.getValue(), args[entry.getKey()]);
//add generic param names (param1, param2, ...) //另外,为每个参数添加param1、param2这样的参数,数字从1开始计算 finalStringgenericParamName= GENERIC_NAME_PREFIX + String.valueOf(i + 1); //ensure not to overwrite parameter named with @Param if (!names.containsValue(genericParamName)) { param.put(genericParamName, args[entry.getKey()]); } i++; } return param; } } }