• mybatis源码阅读-初始化六个工具(六)


    六个基本工具图集

    图片来源:https://my.oschina.net/zudajun/blog/668596

    ObjectFactory

    类图

    接口定义

    public interface ObjectFactory {
        void setProperties(Properties var1);
    
        <T> T create(Class<T> var1);
    
        <T> T create(Class<T> var1, List<Class<?>> var2, List<Object> var3);
    
        <T> boolean isCollection(Class<T> var1);
    }

    使用方式

      ObjectFactory objectFactory=new DefaultObjectFactory();
            List<Classes> classesList=objectFactory.create(ArrayList.class);
            Classes classes = objectFactory.create(Classes.class);
            classes.setName("一年级");
            classesList.add(classes);

    DefaultObjectFactory

    比较简单 我们可以直接拿来自己使用

    public class DefaultObjectFactory implements ObjectFactory, Serializable {
        private static final long serialVersionUID = -8855120656740914948L;
    
        public DefaultObjectFactory() {
        }
    
        /**
         * 创建指定类型的对象 不使用构造函数创建
         * @param type 类型
         * @param <T>
         * @return
         */
        public <T> T create(Class<T> type) {
            return this.create(type, (List)null, (List)null);
        }
    
        /**
         * 创建指定类型的对象
         * @param type 类型
         * @param constructorArgTypes 构造函数参数类型列表
         * @param constructorArgs 构造函数参数列表
         * @param <T>
         * @return
         */
        public <T> T create(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {
            Class<?> classToCreate = this.resolveInterface(type);
            return this.instantiateClass(classToCreate, constructorArgTypes, constructorArgs);
        }
    
        public void setProperties(Properties properties) {
        }
    
        <T> T instantiateClass(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {
            try {
                Constructor constructor;
                //判断是否指定了构造函数初始化
                if (constructorArgTypes != null && constructorArgs != null) {
                    //获得private或public指定参数类型列表的构造函数 注:getConstructor和getDeclaredConstructor的区别是只能获得public
                    constructor = type.getDeclaredConstructor((Class[])constructorArgTypes.toArray(new Class[constructorArgTypes.size()]));
                    //如果是私有的 设置可以访问
                    if (!constructor.isAccessible()) {
                        constructor.setAccessible(true);
                    }
    
                    return constructor.newInstance(constructorArgs.toArray(new Object[constructorArgs.size()]));
                } else {
                    constructor = type.getDeclaredConstructor();
                    if (!constructor.isAccessible()) {
                        constructor.setAccessible(true);
                    }
    
                    return constructor.newInstance();
                }
            } catch (Exception var9) {
                StringBuilder argTypes = new StringBuilder();
                if (constructorArgTypes != null && !constructorArgTypes.isEmpty()) {
                    Iterator i$ = constructorArgTypes.iterator();
    
                    while(i$.hasNext()) {
                        Class<?> argType = (Class)i$.next();
                        argTypes.append(argType.getSimpleName());
                        argTypes.append(",");
                    }
    
                    argTypes.deleteCharAt(argTypes.length() - 1);
                }
    
                StringBuilder argValues = new StringBuilder();
                if (constructorArgs != null && !constructorArgs.isEmpty()) {
                    Iterator i$ = constructorArgs.iterator();
    
                    while(i$.hasNext()) {
                        Object argValue = i$.next();
                        argValues.append(String.valueOf(argValue));
                        argValues.append(",");
                    }
    
                    argValues.deleteCharAt(argValues.length() - 1);
                }
    
                throw new ReflectionException("Error instantiating " + type + " with invalid types (" + argTypes + ") or values (" + argValues + "). Cause: " + var9, var9);
            }
        }
    
        /**
         * 如果是定义结合类型 类型改为实现类
         * @param type
         * @return
         */
        protected Class<?> resolveInterface(Class<?> type) {
            Class classToCreate;
            if (type != List.class && type != Collection.class && type != Iterable.class) {
                if (type == Map.class) {
                    classToCreate = HashMap.class;
                } else if (type == SortedSet.class) {
                    classToCreate = TreeSet.class;
                } else if (type == Set.class) {
                    classToCreate = HashSet.class;
                } else {
                    classToCreate = type;
                }
            } else {
                classToCreate = ArrayList.class;
            }
    
            return classToCreate;
        }
    
        public <T> boolean isCollection(Class<T> type) {
            return Collection.class.isAssignableFrom(type);
        }
    }

    ReflectorFactory

    作用

    创建reflector并缓存起来

    类图

    接口定义

    public interface ReflectorFactory {
        boolean isClassCacheEnabled();
    
        void setClassCacheEnabled(boolean var1);
    
        Reflector findForClass(Class<?> var1);
    }

    DefaultReflectorFactory

    public class DefaultReflectorFactory implements ReflectorFactory {
        private boolean classCacheEnabled = true;
        //将反射的元数据信息封装保存到Reflector 大大提交了性能
        private final ConcurrentMap<Class<?>, Reflector> reflectorMap = new ConcurrentHashMap();
    
        public DefaultReflectorFactory() {
        }
    
        public boolean isClassCacheEnabled() {
            return this.classCacheEnabled;
        }
    
        public void setClassCacheEnabled(boolean classCacheEnabled) {
            this.classCacheEnabled = classCacheEnabled;
        }
    
        /**
         * 获得指定类型反射元数据信息
         * @param type
         * @return
         */
        public Reflector findForClass(Class<?> type) {
            if (this.classCacheEnabled) {
                Reflector cached = (Reflector)this.reflectorMap.get(type);
                //如果没有缓存则从缓存里面拿
                if (cached == null) {
                    cached = new Reflector(type);
                    this.reflectorMap.put(type, cached);
                }
    
                return cached;
            } else {
                return new Reflector(type);
            }
        }
    }

    Reflector

    作用

    封装反射的元数据信息

    源码

    public class Reflector {
        private static final String[] EMPTY_STRING_ARRAY = new String[0];
        private Class<?> type;
        private String[] readablePropertyNames;
        private String[] writeablePropertyNames;
        private Map<String, Invoker> setMethods;
        private Map<String, Invoker> getMethods;
        private Map<String, Class<?>> setTypes;
        private Map<String, Class<?>> getTypes;
        private Constructor<?> defaultConstructor;
        private Map<String, String> caseInsensitivePropertyMap;
    
        /**
         * 初始化并将对应的元数据信息封装起来
         * @param clazz
         */
        public Reflector(Class<?> clazz) {
            this.readablePropertyNames = EMPTY_STRING_ARRAY;
            this.writeablePropertyNames = EMPTY_STRING_ARRAY;
            //初始化几个map
            this.setMethods = new HashMap();
            this.getMethods = new HashMap();
            this.setTypes = new HashMap();
            this.getTypes = new HashMap();
            this.caseInsensitivePropertyMap = new HashMap();
            this.type = clazz;
            //反射查找默认构造函数到defaultConstructor
            this.addDefaultConstructor(clazz);
            //反射获得所有的get方法元数据保存到以Invoker保存getMethods
            this.addGetMethods(clazz);
            //反射获得所有的set方法元数据以invokersetMethods
            this.addSetMethods(clazz);
            //反射获得所有的Fields元数据
            this.addFields(clazz);
            this.readablePropertyNames = (String[])this.getMethods.keySet().toArray(new String[this.getMethods.keySet().size()]);
            this.writeablePropertyNames = (String[])this.setMethods.keySet().toArray(new String[this.setMethods.keySet().size()]);
            String[] arr$ = this.readablePropertyNames;
            int len$ = arr$.length;
    
            int i$;
            String propName;
            for(i$ = 0; i$ < len$; ++i$) {
                propName = arr$[i$];
                this.caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName);
            }
    
            arr$ = this.writeablePropertyNames;
            len$ = arr$.length;
    
            for(i$ = 0; i$ < len$; ++i$) {
                propName = arr$[i$];
                this.caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName);
            }
    
        }
    
        private void addDefaultConstructor(Class<?> clazz) {
            Constructor<?>[] consts = clazz.getDeclaredConstructors();
            Constructor[] arr$ = consts;
            int len$ = consts.length;
    
            for(int i$ = 0; i$ < len$; ++i$) {
                Constructor<?> constructor = arr$[i$];
                if (constructor.getParameterTypes().length == 0) {
                    if (canAccessPrivateMethods()) {
                        try {
                            constructor.setAccessible(true);
                        } catch (Exception var8) {
                            ;
                        }
                    }
    
                    if (constructor.isAccessible()) {
                        this.defaultConstructor = constructor;
                    }
                }
            }
    
        }
    
        private void addGetMethods(Class<?> cls) {
            Map<String, List<Method>> conflictingGetters = new HashMap();
            Method[] methods = this.getClassMethods(cls);
            Method[] arr$ = methods;
            int len$ = methods.length;
    
            for(int i$ = 0; i$ < len$; ++i$) {
                Method method = arr$[i$];
                String name = method.getName();
                if (name.startsWith("get") && name.length() > 3) {
                    if (method.getParameterTypes().length == 0) {
                        name = PropertyNamer.methodToProperty(name);
                        this.addMethodConflict(conflictingGetters, name, method);
                    }
                } else if (name.startsWith("is") && name.length() > 2 && method.getParameterTypes().length == 0) {
                    name = PropertyNamer.methodToProperty(name);
                    this.addMethodConflict(conflictingGetters, name, method);
                }
            }
    
            this.resolveGetterConflicts(conflictingGetters);
        }
    
        private void resolveGetterConflicts(Map<String, List<Method>> conflictingGetters) {
            Iterator i$ = conflictingGetters.keySet().iterator();
    
            while(true) {
                while(i$.hasNext()) {
                    String propName = (String)i$.next();
                    List<Method> getters = (List)conflictingGetters.get(propName);
                    Iterator<Method> iterator = getters.iterator();
                    Method firstMethod = (Method)iterator.next();
                    if (getters.size() == 1) {
                        this.addGetMethod(propName, firstMethod);
                    } else {
                        Method getter = firstMethod;
                        Class getterType = firstMethod.getReturnType();
    
                        while(iterator.hasNext()) {
                            Method method = (Method)iterator.next();
                            Class<?> methodType = method.getReturnType();
                            if (methodType.equals(getterType)) {
                                throw new ReflectionException("Illegal overloaded getter method with ambiguous type for property " + propName + " in class " + firstMethod.getDeclaringClass() + ".  This breaks the JavaBeans " + "specification and can cause unpredicatble results.");
                            }
    
                            if (!methodType.isAssignableFrom(getterType)) {
                                if (!getterType.isAssignableFrom(methodType)) {
                                    throw new ReflectionException("Illegal overloaded getter method with ambiguous type for property " + propName + " in class " + firstMethod.getDeclaringClass() + ".  This breaks the JavaBeans " + "specification and can cause unpredicatble results.");
                                }
    
                                getter = method;
                                getterType = methodType;
                            }
                        }
    
                        this.addGetMethod(propName, getter);
                    }
                }
    
                return;
            }
        }
    
        private void addGetMethod(String name, Method method) {
            if (this.isValidPropertyName(name)) {
                this.getMethods.put(name, new MethodInvoker(method));
                Type returnType = TypeParameterResolver.resolveReturnType(method, this.type);
                this.getTypes.put(name, this.typeToClass(returnType));
            }
    
        }
    
        private void addSetMethods(Class<?> cls) {
            Map<String, List<Method>> conflictingSetters = new HashMap();
            Method[] methods = this.getClassMethods(cls);
            Method[] arr$ = methods;
            int len$ = methods.length;
    
            for(int i$ = 0; i$ < len$; ++i$) {
                Method method = arr$[i$];
                String name = method.getName();
                if (name.startsWith("set") && name.length() > 3 && method.getParameterTypes().length == 1) {
                    name = PropertyNamer.methodToProperty(name);
                    this.addMethodConflict(conflictingSetters, name, method);
                }
            }
    
            this.resolveSetterConflicts(conflictingSetters);
        }
    
        private void addMethodConflict(Map<String, List<Method>> conflictingMethods, String name, Method method) {
            List<Method> list = (List)conflictingMethods.get(name);
            if (list == null) {
                list = new ArrayList();
                conflictingMethods.put(name, list);
            }
    
            ((List)list).add(method);
        }
    
        private void resolveSetterConflicts(Map<String, List<Method>> conflictingSetters) {
            Iterator i$ = conflictingSetters.keySet().iterator();
    
            while(true) {
                while(i$.hasNext()) {
                    String propName = (String)i$.next();
                    List<Method> setters = (List)conflictingSetters.get(propName);
                    Method firstMethod = (Method)setters.get(0);
                    if (setters.size() == 1) {
                        this.addSetMethod(propName, firstMethod);
                    } else {
                        Class<?> expectedType = (Class)this.getTypes.get(propName);
                        if (expectedType == null) {
                            throw new ReflectionException("Illegal overloaded setter method with ambiguous type for property " + propName + " in class " + firstMethod.getDeclaringClass() + ".  This breaks the JavaBeans " + "specification and can cause unpredicatble results.");
                        }
    
                        Iterator<Method> methods = setters.iterator();
                        Method setter = null;
    
                        while(methods.hasNext()) {
                            Method method = (Method)methods.next();
                            if (method.getParameterTypes().length == 1 && expectedType.equals(method.getParameterTypes()[0])) {
                                setter = method;
                                break;
                            }
                        }
    
                        if (setter == null) {
                            throw new ReflectionException("Illegal overloaded setter method with ambiguous type for property " + propName + " in class " + firstMethod.getDeclaringClass() + ".  This breaks the JavaBeans " + "specification and can cause unpredicatble results.");
                        }
    
                        this.addSetMethod(propName, setter);
                    }
                }
    
                return;
            }
        }
    
        private void addSetMethod(String name, Method method) {
            if (this.isValidPropertyName(name)) {
                this.setMethods.put(name, new MethodInvoker(method));
                Type[] paramTypes = TypeParameterResolver.resolveParamTypes(method, this.type);
                this.setTypes.put(name, this.typeToClass(paramTypes[0]));
            }
    
        }
    
        private Class<?> typeToClass(Type src) {
            Class<?> result = null;
            if (src instanceof Class) {
                result = (Class)src;
            } else if (src instanceof ParameterizedType) {
                result = (Class)((ParameterizedType)src).getRawType();
            } else if (src instanceof GenericArrayType) {
                Type componentType = ((GenericArrayType)src).getGenericComponentType();
                if (componentType instanceof Class) {
                    result = Array.newInstance((Class)componentType, 0).getClass();
                } else {
                    Class<?> componentClass = this.typeToClass(componentType);
                    result = Array.newInstance(componentClass, 0).getClass();
                }
            }
    
            if (result == null) {
                result = Object.class;
            }
    
            return result;
        }
    
        private void addFields(Class<?> clazz) {
            Field[] fields = clazz.getDeclaredFields();
            Field[] arr$ = fields;
            int len$ = fields.length;
    
            for(int i$ = 0; i$ < len$; ++i$) {
                Field field = arr$[i$];
                if (canAccessPrivateMethods()) {
                    try {
                        field.setAccessible(true);
                    } catch (Exception var8) {
                        ;
                    }
                }
    
                if (field.isAccessible()) {
                    if (!this.setMethods.containsKey(field.getName())) {
                        int modifiers = field.getModifiers();
                        if (!Modifier.isFinal(modifiers) || !Modifier.isStatic(modifiers)) {
                            this.addSetField(field);
                        }
                    }
    
                    if (!this.getMethods.containsKey(field.getName())) {
                        this.addGetField(field);
                    }
                }
            }
    
            if (clazz.getSuperclass() != null) {
                this.addFields(clazz.getSuperclass());
            }
    
        }
    
        private void addSetField(Field field) {
            if (this.isValidPropertyName(field.getName())) {
                this.setMethods.put(field.getName(), new SetFieldInvoker(field));
                Type fieldType = TypeParameterResolver.resolveFieldType(field, this.type);
                this.setTypes.put(field.getName(), this.typeToClass(fieldType));
            }
    
        }
    
        private void addGetField(Field field) {
            if (this.isValidPropertyName(field.getName())) {
                this.getMethods.put(field.getName(), new GetFieldInvoker(field));
                Type fieldType = TypeParameterResolver.resolveFieldType(field, this.type);
                this.getTypes.put(field.getName(), this.typeToClass(fieldType));
            }
    
        }
    
        private boolean isValidPropertyName(String name) {
            return !name.startsWith("$") && !"serialVersionUID".equals(name) && !"class".equals(name);
        }
    
        private Method[] getClassMethods(Class<?> cls) {
            Map<String, Method> uniqueMethods = new HashMap();
    
            for(Class currentClass = cls; currentClass != null; currentClass = currentClass.getSuperclass()) {
                this.addUniqueMethods(uniqueMethods, currentClass.getDeclaredMethods());
                Class<?>[] interfaces = currentClass.getInterfaces();
                Class[] arr$ = interfaces;
                int len$ = interfaces.length;
    
                for(int i$ = 0; i$ < len$; ++i$) {
                    Class<?> anInterface = arr$[i$];
                    this.addUniqueMethods(uniqueMethods, anInterface.getMethods());
                }
            }
    
            Collection<Method> methods = uniqueMethods.values();
            return (Method[])methods.toArray(new Method[methods.size()]);
        }
    
        private void addUniqueMethods(Map<String, Method> uniqueMethods, Method[] methods) {
            Method[] arr$ = methods;
            int len$ = methods.length;
    
            for(int i$ = 0; i$ < len$; ++i$) {
                Method currentMethod = arr$[i$];
                if (!currentMethod.isBridge()) {
                    String signature = this.getSignature(currentMethod);
                    if (!uniqueMethods.containsKey(signature)) {
                        if (canAccessPrivateMethods()) {
                            try {
                                currentMethod.setAccessible(true);
                            } catch (Exception var9) {
                                ;
                            }
                        }
    
                        uniqueMethods.put(signature, currentMethod);
                    }
                }
            }
    
        }
    
        private String getSignature(Method method) {
            StringBuilder sb = new StringBuilder();
            Class<?> returnType = method.getReturnType();
            if (returnType != null) {
                sb.append(returnType.getName()).append('#');
            }
    
            sb.append(method.getName());
            Class<?>[] parameters = method.getParameterTypes();
    
            for(int i = 0; i < parameters.length; ++i) {
                if (i == 0) {
                    sb.append(':');
                } else {
                    sb.append(',');
                }
    
                sb.append(parameters[i].getName());
            }
    
            return sb.toString();
        }
    
        private static boolean canAccessPrivateMethods() {
            try {
                SecurityManager securityManager = System.getSecurityManager();
                if (null != securityManager) {
                    securityManager.checkPermission(new ReflectPermission("suppressAccessChecks"));
                }
    
                return true;
            } catch (SecurityException var1) {
                return false;
            }
        }
    
        public Class<?> getType() {
            return this.type;
        }
    
        public Constructor<?> getDefaultConstructor() {
            if (this.defaultConstructor != null) {
                return this.defaultConstructor;
            } else {
                throw new ReflectionException("There is no default constructor for " + this.type);
            }
        }
    
        public boolean hasDefaultConstructor() {
            return this.defaultConstructor != null;
        }
    
        public Invoker getSetInvoker(String propertyName) {
            Invoker method = (Invoker)this.setMethods.get(propertyName);
            if (method == null) {
                throw new ReflectionException("There is no setter for property named '" + propertyName + "' in '" + this.type + "'");
            } else {
                return method;
            }
        }
    
        public Invoker getGetInvoker(String propertyName) {
            Invoker method = (Invoker)this.getMethods.get(propertyName);
            if (method == null) {
                throw new ReflectionException("There is no getter for property named '" + propertyName + "' in '" + this.type + "'");
            } else {
                return method;
            }
        }
    
        public Class<?> getSetterType(String propertyName) {
            Class<?> clazz = (Class)this.setTypes.get(propertyName);
            if (clazz == null) {
                throw new ReflectionException("There is no setter for property named '" + propertyName + "' in '" + this.type + "'");
            } else {
                return clazz;
            }
        }
    
        public Class<?> getGetterType(String propertyName) {
            Class<?> clazz = (Class)this.getTypes.get(propertyName);
            if (clazz == null) {
                throw new ReflectionException("There is no getter for property named '" + propertyName + "' in '" + this.type + "'");
            } else {
                return clazz;
            }
        }
    
        public String[] getGetablePropertyNames() {
            return this.readablePropertyNames;
        }
    
        public String[] getSetablePropertyNames() {
            return this.writeablePropertyNames;
        }
    
        public boolean hasSetter(String propertyName) {
            return this.setMethods.keySet().contains(propertyName);
        }
    
        public boolean hasGetter(String propertyName) {
            return this.getMethods.keySet().contains(propertyName);
        }
    
        public String findPropertyName(String name) {
            return (String)this.caseInsensitivePropertyMap.get(name.toUpperCase(Locale.ENGLISH));
        }
    }

     Invoker

    作用

    用于封装方法filed设置的值的动作

    类图

    接口定义

    public interface Invoker {
        Object invoke(Object var1, Object[] var2) throws IllegalAccessException, InvocationTargetException;
    
        Class<?> getType();
    }

    SetFieldInvoker

    /**
     * 封装filed元数据信息
     */
    public class SetFieldInvoker implements Invoker {
        private Field field;
    
        public SetFieldInvoker(Field field) {
            this.field = field;
        }
    
        //给指定对象的当前属性设置值
        public Object invoke(Object target, Object[] args) throws IllegalAccessException, InvocationTargetException {
            this.field.set(target, args[0]);
            return null;
        }
    
        public Class<?> getType() {
            return this.field.getType();
        }
    }

    GetFieldInvoker

    /**
     * 封装Filed信息 提供getfiled的调用实现
     */
    public class GetFieldInvoker implements Invoker {
        private Field field;
    
        public GetFieldInvoker(Field field) {
            this.field = field;
        }
    
        public Object invoke(Object target, Object[] args) throws IllegalAccessException, InvocationTargetException {
            return this.field.get(target);
        }
    
        public Class<?> getType() {
            return this.field.getType();
        }
    }

    MethodInvoker

    /**
     * 方法元数据封装 以及提供调用的方法
     */
    public class MethodInvoker implements Invoker {
        private Class<?> type;
        private Method method;
    
        public MethodInvoker(Method method) {
            this.method = method;
            if (method.getParameterTypes().length == 1) {
                this.type = method.getParameterTypes()[0];
            } else {
                this.type = method.getReturnType();
            }
    
        }
    
        public Object invoke(Object target, Object[] args) throws IllegalAccessException, InvocationTargetException {
            return this.method.invoke(target, args);
        }
    
        public Class<?> getType() {
            return this.type;
        }
    }

     反射工具的使用

        //对象创建工厂
            ObjectFactory objectFactory=new DefaultObjectFactory();
            //反射创建ArrayList
            List<Classes> classesList=objectFactory.create(ArrayList.class);
            //反射类创建工厂 必须单例哟
            ReflectorFactory reflectorFactory= new DefaultReflectorFactory();
            Classes classes = objectFactory.create(Classes.class);
            //获得Classes所有filed和get的元数据封装信息 并缓存 下次再次获取就是使用缓存
            Reflector classesReflector= reflectorFactory.findForClass(Classes.class);
            //获得对应Filed或者setMethod的Invoker封装并调用设置值
            classesReflector.getSetInvoker("name").invoke(classes,new Object[]{"一年级"});
            classesList.add(classes);
            for (Classes item:
                 classesList) {
                System.out.print(item.getName());
    
            }

    XPath、EntityResolver

    说明

    解析xml使用非mybatis内部工具类 就不贴源码了

    使用方式

    1.解析如下xml

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="classes">
        <select id="selectAll" resultType="com.liqiang.entity.Classes">
            select * from classes
        </select>
        <insert id="insert"  useGeneratedKeys="true" keyProperty="id" parameterType="com.liqiang.entity.Classes">
            insert INTO classes(name) VALUES (#{name});
        </insert>
        <update id="update"  parameterType="com.liqiang.entity.Classes">
            UPDATE classes set name=#{name} where id=#{id};
        </update>
        <delete id="delete" parameterType="int">
            delete from classes where id=#{id};
        </delete>
    </mapper>

    2.代码

     public static  void parseXml() throws IOException, ParserConfigurationException, SAXException, XPathExpressionException {
            DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
            builderFactory.setValidating(false);
    
            DocumentBuilder builder = builderFactory.newDocumentBuilder();
            //不加这句话默认会去http://mybatis.org/dtd/mybatis-3-config.dtd 加上的话 会从本地dtd查找
            builder.setEntityResolver(new XMLMapperEntityResolver());
            InputSource inputSource = new InputSource(Resources.getResourceAsStream("ClassesMapper.xml"));
    
            Document document = builder.parse(inputSource);
    
            XPathFactory xPathFactory = XPathFactory.newInstance();
            XPath xpath = xPathFactory.newXPath();
            //获得mapper节点的namespace的值
            String value = (String) xpath.evaluate("/mapper/@namespace", document, XPathConstants.STRING);
            System.out.println("namespace="" + value + """);
            //获得mapper节点
            Node mapperNode = (Node) xpath.evaluate("/mapper", document, XPathConstants.NODE);
            NodeList nodeList= mapperNode.getChildNodes();
            System.out.println(nodeList.getLength());
            for(int i=0;i<nodeList.getLength();i++){
               Node node= nodeList.item(i+1);
               //因为换行符也是一个节点所以只处理Element节点
               if(node instanceof Element) {
                   System.out.print("text" + node.getTextContent());
                   System.out.println("属性值:");
                   NamedNodeMap attributeNodes = node.getAttributes();
                   for (int j = 0; j < attributeNodes.getLength(); j++) {
                       Node n = attributeNodes.item(j);
                       System.out.println(n.getNodeName() + "="" + n.getNodeValue() + """);
                   }
               }
            }
    
        }
  • 相关阅读:
    增强Eclipse ,MyEclipse的代码提示功能(图文教程)
    大型网站系统架构分析
    大型网站后台架构的Web Server与缓存
    大型网站架构演变和知识体系
    说说大型高并发高负载网站的系统架构
    UVa 11300 Spreading the Wealth 数学题
    HDU 1021 Fibonacci Again 简单数学题
    删除安卓系统自带的软件的方法
    HDU 1207 汉诺塔II 动态规划
    LA 3708 Graveyard 模拟题
  • 原文地址:https://www.cnblogs.com/LQBlog/p/10684742.html
Copyright © 2020-2023  润新知