- 浏览: 984429 次
文章分类
- 全部博客 (428)
- Hadoop (2)
- HBase (1)
- ELK (1)
- ActiveMQ (13)
- Kafka (5)
- Redis (14)
- Dubbo (1)
- Memcached (5)
- Netty (56)
- Mina (34)
- NIO (51)
- JUC (53)
- Spring (13)
- Mybatis (17)
- MySQL (21)
- JDBC (12)
- C3P0 (5)
- Tomcat (13)
- SLF4J-log4j (9)
- P6Spy (4)
- Quartz (12)
- Zabbix (7)
- JAVA (9)
- Linux (15)
- HTML (9)
- Lucene (0)
- JS (2)
- WebService (1)
- Maven (4)
- Oracle&MSSQL (14)
- iText (11)
- Development Tools (8)
- UTILS (4)
- LIFE (8)
最新评论
-
Donald_Draper:
Donald_Draper 写道刘落落cici 写道能给我发一 ...
DatagramChannelImpl 解析三(多播) -
Donald_Draper:
刘落落cici 写道能给我发一份这个类的源码吗Datagram ...
DatagramChannelImpl 解析三(多播) -
lyfyouyun:
请问楼主,执行消息发送的时候,报错:Transport sch ...
ActiveMQ连接工厂、连接详解 -
ezlhq:
关于 PollArrayWrapper 状态含义猜测:参考 S ...
WindowsSelectorImpl解析一(FdMap,PollArrayWrapper) -
flyfeifei66:
打算使用xmemcache作为memcache的客户端,由于x ...
Memcached分布式客户端(Xmemcached)
Mybatis的MetaObject解析:http://donald-draper.iteye.com/admin/blogs/2338818
在上篇分析MetaObejct时候,MetaObejct的方法的实现是依赖ObjectWrapper,ObjectWrapper依赖于MetaClass,而MetaClass依赖于Reflector,这一节我们就来看看Reflector
//Reflector
来看addDefaultConstructor
初始化默认构造函数为,无参构造函数
来看addGetMethods
将Class的Get方法添加到
来看addSetMethods
来看addFields
总结:
从以上分析,Reflector构造函数,所做的工作为,初始构造函数,将Class的set与get方法及参数添加到setMethods,getMethods,setTypes,getTypes对应的Map中,setMethods,getMethods Map的key属性名,value为对应的方法,然后初始化可读,可写,及大小写不明感属性集合。
在上篇分析MetaObejct时候,MetaObejct的方法的实现是依赖ObjectWrapper,ObjectWrapper依赖于MetaClass,而MetaClass依赖于Reflector,这一节我们就来看看Reflector
//Reflector
public class Reflector { private static boolean classCacheEnabled = true; private static final String EMPTY_STRING_ARRAY[] = new String[0]; private static final Map REFLECTOR_MAP = new ConcurrentHashMap(); private Class type; private String readablePropertyNames[];//可读属性名 private String writeablePropertyNames[];//可写属性名 private Map setMethods;Map<String,MethodInvoker> private Map getMethods;Map<String,MethodInvoker> private Map setTypes;Map<String,Class> private Map getTypes;Map<String,Class> private Constructor defaultConstructor;//默认构造函数 private Map caseInsensitivePropertyMap;//大小写不敏感属性Map //构造Class对应的Reflector public static Reflector forClass(Class clazz) { if(classCacheEnabled) { //如果缓存状态开启,则从REFLECTOR_MAP获取对应的Reflector,没有则重新构建 Reflector cached = (Reflector)REFLECTOR_MAP.get(clazz); if(cached == null) { cached = new Reflector(clazz); REFLECTOR_MAP.put(clazz, cached); } return cached; } else { return new Reflector(clazz); } } private Reflector(Class clazz) { readablePropertyNames = EMPTY_STRING_ARRAY;//可读属性名 writeablePropertyNames = EMPTY_STRING_ARRAY;//可写属性名 setMethods = new HashMap();//Set方法Map getMethods = new HashMap();//Get方法Map setTypes = new HashMap(); getTypes = new HashMap(); caseInsensitivePropertyMap = new HashMap();//大小写不敏感属性Map type = clazz; addDefaultConstructor(clazz); addGetMethods(clazz); addSetMethods(clazz); addFields(clazz); readablePropertyNames = (String[])getMethods.keySet().toArray(new String[getMethods.keySet().size()]); writeablePropertyNames = (String[])setMethods.keySet().toArray(new String[setMethods.keySet().size()]); //将可读属性添加大小写不敏感属性Map String arr$[] = readablePropertyNames; int len$ = arr$.length; for(int i$ = 0; i$ < len$; i$++) { String propName = arr$[i$]; caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName); } //将可写属性添加大小写不敏感属性Map arr$ = writeablePropertyNames; len$ = arr$.length; for(int i$ = 0; i$ < len$; i$++) { String propName = arr$[i$]; caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName); } } }
来看addDefaultConstructor
初始化默认构造函数为,无参构造函数
private void addDefaultConstructor(Class clazz) { Constructor consts[] = clazz.getDeclaredConstructors(); Constructor arr$[] = consts; int len$ = arr$.length; for(int i$ = 0; i$ < len$; i$++) { Constructor constructor = arr$[i$]; if(constructor.getParameterTypes().length != 0) continue; if(canAccessPrivateMethods()) try { constructor.setAccessible(true); } catch(Exception e) { } if(constructor.isAccessible()) defaultConstructor = constructor; } }
来看addGetMethods
将Class的Get方法添加到
private void addGetMethods(Class cls) { Map conflictingGetters = new HashMap(); Method methods[] = getClassMethods(cls); Method arr$[] = methods; int len$ = arr$.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); //将name对应的get方法添加到conflictingGetters-Map中 addMethodConflict(conflictingGetters, name, method); } continue; } if(name.startsWith("is") && name.length() > 2 && method.getParameterTypes().length == 0) { name = PropertyNamer.methodToProperty(name); addMethodConflict(conflictingGetters, name, method); } } //解决方法冲突 resolveGetterConflicts(conflictingGetters); } private void addMethodConflict(Map conflictingMethods, String name, Method method) { List list = (List)conflictingMethods.get(name); if(list == null) { list = new ArrayList(); conflictingMethods.put(name, list); } list.add(method); } private void resolveGetterConflicts(Map conflictingGetters) { for(Iterator i$ = conflictingGetters.keySet().iterator(); i$.hasNext();) { String propName = (String)i$.next(); List getters = (List)conflictingGetters.get(propName); Iterator iterator = getters.iterator(); Method firstMethod = (Method)iterator.next(); if(getters.size() == 1) { addGetMethod(propName, firstMethod); } else { Method getter = firstMethod; Class getterType = firstMethod.getReturnType(); do { if(!iterator.hasNext()) break; Method method = (Method)iterator.next(); Class methodType = method.getReturnType(); if(methodType.equals(getterType)) throw new ReflectionException((new StringBuilder()).append("Illegal overloaded getter method with ambiguous type for property ").append(propName).append(" in class ").append(firstMethod.getDeclaringClass()).append(". This breaks the JavaBeans ").append("specification and can cause unpredicatble results.").toString()); if(!methodType.isAssignableFrom(getterType)) if(getterType.isAssignableFrom(methodType)) { getter = method; getterType = methodType; } else { throw new ReflectionException((new StringBuilder()).append("Illegal overloaded getter method with ambiguous type for property ").append(propName).append(" in class ").append(firstMethod.getDeclaringClass()).append(". This breaks the JavaBeans ").append("specification and can cause unpredicatble results.").toString()); } } while(true); //将name对应的get方法添加到getMethods集合中 addGetMethod(propName, getter); } } } //将name对应的get方法添加到getMethods集合中 private void addGetMethod(String name, Method method) { if(isValidPropertyName(name)) { getMethods.put(name, new MethodInvoker(method)); getTypes.put(name, method.getReturnType()); } }
来看addSetMethods
private void addSetMethods(Class cls) { Map conflictingSetters = new HashMap(); Method methods[] = getClassMethods(cls); Method arr$[] = methods; int len$ = arr$.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); //将name对应的set方法添加到conflictingSetters-Map中 addMethodConflict(conflictingSetters, name, method); } } //解决方法冲突 resolveSetterConflicts(conflictingSetters); } private void addMethodConflict(Map conflictingMethods, String name, Method method) { List list = (List)conflictingMethods.get(name); if(list == null) { list = new ArrayList(); conflictingMethods.put(name, list); } list.add(method); } private void resolveSetterConflicts(Map conflictingSetters) { Iterator i$ = conflictingSetters.keySet().iterator(); do { if(!i$.hasNext()) break; String propName = (String)i$.next(); List setters = (List)conflictingSetters.get(propName); Method firstMethod = (Method)setters.get(0); if(setters.size() == 1) { addSetMethod(propName, firstMethod); continue; } Class expectedType = (Class)getTypes.get(propName); if(expectedType == null) throw new ReflectionException((new StringBuilder()).append("Illegal overloaded setter method with ambiguous type for property ").append(propName).append(" in class ").append(firstMethod.getDeclaringClass()).append(". This breaks the JavaBeans ").append("specification and can cause unpredicatble results.").toString()); Iterator methods = setters.iterator(); Method setter = null; do { if(!methods.hasNext()) break; Method method = (Method)methods.next(); if(method.getParameterTypes().length != 1 || !expectedType.equals(method.getParameterTypes()[0])) continue; setter = method; break; } while(true); if(setter == null) throw new ReflectionException((new StringBuilder()).append("Illegal overloaded setter method with ambiguous type for property ").append(propName).append(" in class ").append(firstMethod.getDeclaringClass()).append(". This breaks the JavaBeans ").append("specification and can cause unpredicatble results.").toString()); //将对应的set方法添加到setMethods-map中 addSetMethod(propName, setter); } while(true); } private void addSetMethod(String name, Method method) { if(isValidPropertyName(name)) { setMethods.put(name, new MethodInvoker(method)); setTypes.put(name, method.getParameterTypes()[0]); } }
来看addFields
private void addFields(Class clazz) { Field fields[] = clazz.getDeclaredFields(); Field arr$[] = fields; int len$ = arr$.length; for(int i$ = 0; i$ < len$; i$++) { Field field = arr$[i$]; if(canAccessPrivateMethods()) try { field.setAccessible(true); } catch(Exception e) { } if(!field.isAccessible()) continue; if(!setMethods.containsKey(field.getName())) addSetField(field); if(!getMethods.containsKey(field.getName())) addGetField(field); } if(clazz.getSuperclass() != null) addFields(clazz.getSuperclass()); } //将Field的对应set方法,及参数类型添加到setMethods,setTypes-Map中 private void addSetField(Field field) { if(isValidPropertyName(field.getName())) { setMethods.put(field.getName(), new SetFieldInvoker(field)); setTypes.put(field.getName(), field.getType()); } } //将Field的对应get方法,及参数类型添加到setMethods,setTypes-Map中 private void addGetField(Field field) { if(isValidPropertyName(field.getName())) { getMethods.put(field.getName(), new GetFieldInvoker(field)); getTypes.put(field.getName(), field.getType()); } }
总结:
从以上分析,Reflector构造函数,所做的工作为,初始构造函数,将Class的set与get方法及参数添加到setMethods,getMethods,setTypes,getTypes对应的Map中,setMethods,getMethods Map的key属性名,value为对应的方法,然后初始化可读,可写,及大小写不明感属性集合。
发表评论
-
Mybatis缓存实现
2016-12-07 10:36 983SqlSessionFactory初始化:http://don ... -
DefaultSqlSession第三讲-事务提交,回滚,关闭SqlSession,清除缓存
2016-11-20 11:07 5714上面两篇讲过query和update及flushStateme ... -
DefaultSqlSession第二讲-更新,刷新Statement
2016-11-20 11:06 635上一篇文章中,我们讲到DefaultSqlSession的查询 ... -
DefaultSqlSession第一讲query解析
2016-11-20 11:06 1631上一篇文章:我们说过DefaultSqlSession,Def ... -
Mybatis的SqlSession解析
2016-11-20 11:02 2565在前文中,Mybatis使用教程中,有下面一段代码: Sql ... -
Mybatis的MetaObject解析
2016-11-18 11:40 9583SqlSessionFactory初始化:http://don ... -
mybatis 动态标签语句的解析(BoundSql)
2016-10-30 09:48 5765SqlSessionFactory初始化:http://don ... -
Mybatis的Environment解析详解
2016-10-29 18:28 1998SqlSessionFactory初始化:http://don ... -
Mybatis 解析Mapper(class)
2016-10-26 11:44 3364SqlSessionFactory初始化:http://don ... -
Mybatis加载解析Mapper(xml)文件第二讲
2016-10-25 21:30 4804SqlSessionFactory初始化:http://don ... -
Mybatis加载解析Mapper(xml)文件第一讲
2016-10-25 16:51 6198SqlSessionFactory初始化:http://don ... -
SqlSessionFactory初始化
2016-10-20 15:38 2460mybatis 使用教程:http://donald-drap ... -
mybatis 使用教程
2016-10-14 09:03 914Myeclispe下mybatis generator的使 ... -
Spring+Mybatis多数据源的实现
2016-09-21 18:15 3095浅谈Spring事务隔离级别:http://www.cnblo ... -
mybaitis CDATA 防止字符被解析
2016-08-17 18:45 727在使用mybatis 时我们sql是写在xml 映射文件中,如 ... -
Myeclispe下mybatis generator的使用
2016-07-05 18:05 1379准备:下载附件包解压到myeclispe的dropins文件夹 ...
相关推荐
MyBatis日志解析工具支持MyBatis3.0以上版本,能够将Mybatis打印的SQL日志转换成SQL语句。 使用方法请查看 https://blog.csdn.net/warehouse666/article/details/90111704
mybatis SQL日志解析;查看日志时mybatis打印的日志查询条件以及参数不是拼接好的,想复制对应sql在本地执行时比较麻烦,通过前端编写页面进行日志解析,拼接sql中的问号以及参数变课轻松实现
MyBatis 源码解析:通过源码深入理解 SQL 的执行过程 抓下来打包成了HTML文件, 方便离线观看
项目需要springboot 可以绕过mybatis xml加载直接解析带标签的sql 演示代码,给需要的码农
Spring整合Mybatis源码解析
该工具可以将mybatis输出的sql日志提取出来,并将其格式化为可以直接执行的sql语句,节约开发人员时间
MyBatis源码解析
Mybatis源码解析设计源码:该项目基于Java开发,包含37个文件,主要使用Java语言。该项目旨在对Mybatis框架的源代码进行深入解析,以帮助开发者更好地理解和使用Mybatis,提高开发效率和质量。
Mybatis日志中的SQL解析工具(网页版) 说明:复制日志时,必须注意,日志必须包含Preparing:和Parameters:全部内容,而且日志换行格式要保留,不要复制成纯文本,直接ctrl+c即可。
mybatis源码解析视频的讲解是由某知名老师讲解。包你学完可以完全理解mybatis框架实现原理等。
MyBatis 3.x 源码深度解析与最佳实践 MyBatis 是当前最流行的 Java 持久层框架之一,其通过 XML 配置的方式消除了绝大部分 JDBC 重复代码以及参数的设置,结果集的映射。为了更好地学习和理解 MyBatis 背后的设计...
MyBatis的配置文件解析过程是MyBatis的核心组件之一,负责解析MyBatis的配置文件,并将其转换为 Configuration 对象。配置文件解析过程主要包括解析节点、节点、节点、节点、节点、节点等。 2.1.1 解析节点 节点...
mybatis sql解析,自动填充sql参数,服务器日志sql直接执行
该学习项目记录了湖北师范大学后端开发过程中的SpringBoot、Hibernate和MyBatis框架源码解析,包含252个文件,主要包括91个Java源文件、87个XML配置文件、19个YAML文件,以及少量其他类型文件。项目内容旨在帮助...
MyBatis作为一款优秀的持久层框架,以其...通过本文的解析与实战应用,相信大家对MyBatis有了更深入的了解和认识。在实际应用中,我们应结合业务需求和技术特点,合理选择和使用MyBatis,以提升系统的性能和稳定性。
适用场景:生产环境从sql日志获取可执行sql语句 使用方法:从日志中获取完整的sql片段(可以前后多复制一部分,确保准确性),打开html文件,粘贴到输入框中点击解析sql,获得可执行的sql
### MyBatis解析配置文件的工具类知识点解析 在Java Web开发中,MyBatis作为一款优秀的持久层框架,能够极大地简化数据访问层(DAO)的编码工作,提高开发效率。本文将详细介绍一个用于初始化MyBatis环境并提供获取...
mybatis 3.x源码深度解析与最佳实践.html
在执行SQL后,MyBatis的ParameterHandler、ResultSetHandler和StatementHandler三个接口分别处理参数设置、结果集解析和SQL语句的创建。它们协同工作,确保了数据的正确读写。 思维导图中可能还会涉及MyBatis的插件...
"基于IOC容器实现管理mybatis过程解析" IOC容器是Inversion of Control的缩写,指的是控制反转容器。在软件设计中,控制反转是一种设计原则,它将对象的控制权从对象本身转移到外部容器中,从而实现了对象之间的松...