关于Mybatis的研究之 bean没有set方法 也可以赋值
2013-10-03 16:11
253 查看
1.问题描述
在学习mybatis的时候,发现了一个有趣的现象
如果resultType所指向的bean没有set方法时 在ibatis上是不能成功并且报错误 但在mybatis却是可以的
bean类:
sqlmap如下:
测试类代码如下:
这样User类的属性居然是有值的!!!!
这着实让我很诧异 在排除了是我操作的问题的情况下,最终的造成此现象的根源在于mybatis本身。
于是我有了想看mybatis源码的冲动。。。。
2.分析问题
说实话,这是我第一次正儿八经的看框架源码。
一个字:杂啊!!!
但杂而不乱,我debug了好久才找到了根源
类SetFieldInvoke
原来它利用的是反射原理直接操作属性而非set方法
但有一个问题出现了 User类中的属性都是private的。如果 Field 类中没有setAccessible(true)的话,是不会访问到私有属性的。
在SetFieldInvoke方法中并没有执行此方法啊,但结果确实是给私有属性赋值了。
可以说明一点是setAccessible(true)此方法
肯定是执行了。
剩下的问题是此方法在哪里执行了??
于是我搜索文本setAccessible(true)
果然在org.apache.ibatis.reflection.Reflector
中 发现了此方法在调用
简单来说,就是在初始化的时候就将每个属性都setAccessible(true)了。
谜底已经解开了。
找到谜底固然欣喜,但解开谜底的过程,更让我学到了不少东西。
对反射的一些类有了更深的认识。
更重要的是 学到在一个复杂 的业务面前 设计是多么的重要啊。
在学习mybatis的时候,发现了一个有趣的现象
如果resultType所指向的bean没有set方法时 在ibatis上是不能成功并且报错误 但在mybatis却是可以的
bean类:
sqlmap如下:
测试类代码如下:
@Test public void testNewTable() throws IOException{ String resource = "sqlMap_config.xml"; Reader reader = Resources.getResourceAsReader(resource); SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); SqlSessionFactory factory = builder.build(reader); SqlSession session = factory.openSession(); List<User> list = session.selectList("NewTable.selectAll"); System.out.println( list.get(0) ); }
这样User类的属性居然是有值的!!!!
这着实让我很诧异 在排除了是我操作的问题的情况下,最终的造成此现象的根源在于mybatis本身。
于是我有了想看mybatis源码的冲动。。。。
2.分析问题
说实话,这是我第一次正儿八经的看框架源码。
一个字:杂啊!!!
但杂而不乱,我debug了好久才找到了根源
类SetFieldInvoke
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 { field.set(target, args[0]); return null; } public Class<?> getType() { return field.getType(); } }
field.set(target, args[0]);
原来它利用的是反射原理直接操作属性而非set方法
但有一个问题出现了 User类中的属性都是private的。如果 Field 类中没有setAccessible(true)的话,是不会访问到私有属性的。
在SetFieldInvoke方法中并没有执行此方法啊,但结果确实是给私有属性赋值了。
可以说明一点是setAccessible(true)此方法
肯定是执行了。
剩下的问题是此方法在哪里执行了??
于是我搜索文本setAccessible(true)
果然在org.apache.ibatis.reflection.Reflector
中 发现了此方法在调用
private void addFields(Class<?> clazz) { Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { if (canAccessPrivateMethods()) { try { field.setAccessible(true); } catch (Exception e) { // Ignored. This is only a final precaution, nothing we can do. } } if (field.isAccessible()) { if (!setMethods.containsKey(field.getName())) { // issue 379 - removed the check for final because JDK 1.5 allows // modification of final fields through reflection (JSR-133). (JGB) addSetField(field); } if (!getMethods.containsKey(field.getName())) { addGetField(field); } } } if (clazz.getSuperclass() != null) { addFields(clazz.getSuperclass()); } }
简单来说,就是在初始化的时候就将每个属性都setAccessible(true)了。
谜底已经解开了。
找到谜底固然欣喜,但解开谜底的过程,更让我学到了不少东西。
对反射的一些类有了更深的认识。
更重要的是 学到在一个复杂 的业务面前 设计是多么的重要啊。
相关文章推荐
- 关于Mybatis的研究之 bean没有set方法 也可以赋值
- 关于Mybatis的研究之 bean没有set方法 也可以赋值
- 关于struts2 中action 属性没有 set 方法 依然会注入值的问题(解决)
- 关于mybatis的关联查询中id错误赋值的解决方法
- 关于Java中的构造方法和set方法()给属性赋值
- 关于Enum枚举类没有values()方法却可以在枚举类中使用的问题
- 利用运行时,给UIImageView写一个分类,交换里面的setImage的方法,可以重绘图片,提高内存的利用率(要是没有重绘图片,直接使用系统提供的setImag就会造成占用大量的内存问题)
- 反射给没有set方法的属性赋值
- 反射给没有set方法的属性赋值
- 为什么java序列化接口没有方法却可以完成序列化
- 关于Servlet中HttpServletRequest对象的setCharacterEncoding方法的讨论。
- 关于FireMonkey TGrid赋值的一点小研究
- input文本框没有onchange事件,可以通过下面两种方法实现当input内容改变时触发事件
- 在这里稍稍提一下“敏捷方法”,以后有兴趣还可以继续研究
- 关于javascript中Math对象的属性与方法研究
- 关于notification.setLatestEventInfo()的替代方法
- 关于:安全研究人员发现新木马 可以隐蔽ICMP协议传数据
- XenServer没有自己的文件系统,也就没有自己的ISO Libery,给我们创建虚拟机带来了不少困扰,使用正文这个方法可以不用先安装FileServer
- [工作点滴]属性没有 set/get方法
- java反射机制set方法 连接数据库(还有待修改,没有循环ResultSet对象)