mybatis源码- 反射模块一(跟着MyBatis学反射):类级别信息的封装 (2)

注意, 由于在获取方法时, 通过调用当前类及其除 Object 之外的所有父类的 getDeclaredMethods 方法及 getInterfaces() 方法, 因此, 其获取到的方法是该类及其父类的所有方法。

由此, 产生了一个问题, 如果子类重写了父类中的方法, 如果返回值相同, 则可以通过键重复来去掉。 但是, 如果方法返回值是父类相同实体方法返回值类型的子类, 则就会导致两个方法是同一个方法, 但是签名不同。 因此, 需要解决此类冲突。

解决方法冲突:getter方法冲突解决

private void resolveGetterConflicts(Map<String, List<Method>> conflictingGetters)

到了此步骤的时候, 属性已经以 propName->List<Method> 的形式存在于内存中。 此时, 需要Map<String, List转换为Map<String, Invoker>。

该方法只需要明白下面两个条件就能很清晰了:

返回值类型不同

返回值类型不同, 则哪个方法的返回值是另一个方法返回值类型子类, 就把 propName 指向该方法包装成的 Invoker。 这个很好理解, 毕竟重新(override)重写时, 重写方法的返回值类型可以是被重写方法的子类。

返回值类型相同

按理来说不会出现这种情况, 因为在获取方法的时候已经使用签名去除掉了, 因此此时可以抛出异常。 但是有一种特殊的情况(这个卡了我一段时间):

public boolean isBool() {return true;}// 方法1 public boolean getBool() {return false;}// 方法2

以上情况在 JavaBean 规范中是允许的(但是, 其实方法2几乎大家都不会这么用)。 因此, mybatis 通过以下的方式进行了过滤。

if (!boolean.class.equals(candidateType)) { throw new ReflectionException( "Illegal overloaded getter method with ambiguous type for property " + propName + " in class " + winner.getDeclaringClass() + ". This breaks the JavaBeans specification and can cause unpredictable results."); } else if (candidate.getName().startsWith("is")) { winner = candidate; }

也就是说, mybatis 承认的是方法1这种。 方法2的忽略掉。

解决方法冲突:setter方法冲突解决

刚开始, 我也想不明白, 为什么setter也会出现冲突。毕竟没有返回值类型, 也没有上面的 boolean 特殊情况。 最后发现了, 还有一个情况, 泛型!!

void setId(T id);// 父类 public void setId(String id) {// 子类 // Do nothing }

显然, 遇到此类情况, 显然, 子类中的方法才是我们想要的:

if (paramType1.isAssignableFrom(paramType2)) { return setter2; } else if (paramType2.isAssignableFrom(paramType1)) { return setter1; }

参数中, 父类方法泛型经过类型擦除后, 变成了 Object。 因此, 通过以上的方法, 那个是子类, 我们就获取哪一个。

3 ReflectorFactory

看名称, 工厂方法, 是为了创建和缓存 Reflector 的。

ReflectorFactory

只有三个方法: 是否缓存, 设置要不要缓存, 根据类型查找 Reflector 对象(找不到则创建)。

其与 Reflector 的关系

关系

mybatis 为我们提供了该方法的默认实现 DefaultReflectorFactory。 该类的实现很简单, 就是通过ConcurrentMap<Class<?>, Reflector>对 Reflector进行缓存。

4 MetaClass

MetaClass 通过与属性工具类的结合, 实现了对复杂表达式的解析,实现了获取指定描述信息的功能。

4.1 成员变量

MetaClass 有两个成员变量, 分别是 ReflectorFactory 和 Reflector。

4.2 创建

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpwdzy.html