Mybatis源码解读(二)--反射模块

Mybatis反射模块的代码在org.apache.ibatis.reflection。Mybatis的反射十分强大,对jdk的反射进行了很好的封装,完全可以作为一个独立的工具类在其他项目中使用。

核心类解读

MetaObject:封装了对象的元信息,包装了Mybatis中五个核心的反射类。也是提供给外部使用的反射工具类,通过它可以读取或修改对象的属性。

public class MetaObject {

  //原始的java对象
  private final Object originalObject;
  private final ObjectWrapper objectWrapper;
  private final ObjectFactory objectFactory;
  private final ObjectWrapperFactory objectWrapperFactory;
  private final ReflectorFactory reflectorFactory;

ObjectFactory:对象工厂。Mybatis每次创建结果对象的新实例时,它都会使用ObjectFactory去创建POJO。

public interface ObjectFactory {

  //设置配置信息
  void setProperties(Properties properties);

  //通过无参构造函数创建指定类的对象
  <T> T create(Class<T> type);
  
  //根据参数列表,选择合适的构造函数创建对象
  <T> T create(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs);

  //检测指定类型是否为集合类型
  <T> boolean isCollection(Class<T> type);

}


ReflectorFactory:创建Reflector的工厂类,Reflector是Mybatis反射模块的基础,每个Reflector对象都对应一个类,在其中缓存了反射操作所需要的类的信息。

public interface ReflectorFactory {

  boolean isClassCacheEnabled();

  void setClassCacheEnabled(boolean classCacheEnabled);

  Reflector findForClass(Class<?> type);
}


ObjectWrapper:对象的包装,抽象了对象的属性信息,定义了一系列查询对象属性信息的方法,以及更新属性的方法。

public interface ObjectWrapper {

  //获取对象指定属性的值
  Object get(PropertyTokenizer prop);

  //设置对象指定属性的值
  void set(PropertyTokenizer prop, Object value);

  String findProperty(String name, boolean useCamelCaseMapping);

  String[] getGetterNames();

  String[] getSetterNames();

  Class<?> getSetterType(String name);

  Class<?> getGetterType(String name);

  boolean hasSetter(String name);

  boolean hasGetter(String name);

  MetaObject instantiatePropertyValue(String name, PropertyTokenizer prop, ObjectFactory objectFactory);
  //判断当前对象是否为集合
  boolean isCollection();
  
  //当前集合添加一个元素
  void add(Object element);
  
  //当前集合添加另外一个集合
  <E> void addAll(List<E> element);

}


ObjectWrapperFactory:ObjectWrapper的工厂类,用于创建ObjectWrapper。
 

public interface ObjectWrapperFactory {

  boolean hasWrapperFor(Object object);

  ObjectWrapper getWrapperFor(MetaObject metaObject, Object object);

}

如何使用Mybatis反射模块

模拟一个实体类TUSer

@Data
public class TUser implements Serializable {

	private Integer id;

	private String userName;

}
使用Reflector读取类元信息
ReflectorFactory reflectorFactory = new DefaultReflectorFactory();
Reflector findForClass = reflectorFactory.findForClass(TUser.class);
Constructor<?> defaultConstructor = findForClass.getDefaultConstructor();
String[] getablePropertyNames = findForClass.getGetablePropertyNames();
String[] setablePropertyNames = findForClass.getSetablePropertyNames();
System.out.println(defaultConstructor.getName());
System.out.println(Arrays.toString(getablePropertyNames));
System.out.println(Arrays.toString(setablePropertyNames));
使用ObjectWrapper读取对象信息,并对对象属性进行赋值操作
ObjectFactory objectFactory = new DefaultObjectFactory();
TUser user = objectFactory.create(TUser.class);
ObjectWrapperFactory objectWrapperFactory = new DefaultObjectWrapperFactory();
ReflectorFactory reflectorFactory = new DefaultReflectorFactory();
MetaObject metaObject = MetaObject.forObject(user, objectFactory, objectWrapperFactory, reflectorFactory);
TUser userTemp = new TUser();
ObjectWrapper wrapperForUser = new BeanWrapper(metaObject, userTemp);
String[] getterNames = wrapperForUser.getGetterNames();
String[] setterNames = wrapperForUser.getSetterNames();
System.out.println(Arrays.toString(getterNames));
System.out.println(Arrays.toString(setterNames));

PropertyTokenizer prop = new PropertyTokenizer("userName");
wrapperForUser.set(prop, "test001");
System.out.println(userTemp);
模拟数据库行数据转化成对象
//1.模拟从数据库读取数据
Map<String, Object> dbResult = new HashMap<>();
dbResult.put("id", 1);
dbResult.put("user_name", "test001");
//2.模拟ResultMap映射关系
Map<String, String> mapper = new HashMap<String, String>();
mapper.put("id", "id");
mapper.put("userName", "user_name");

//3.使用反射工具类将行数据转换成pojo
BeanWrapper objectWrapper = (BeanWrapper) metaObject.getObjectWrapper();

Set<Entry<String, String>> entrySet = mapper.entrySet();
for (Entry<String, String> colInfo : entrySet) {
	String propName = colInfo.getKey();
	Object propValue = dbResult.get(colInfo.getValue());
	PropertyTokenizer proTokenizer = new PropertyTokenizer(propName);
	objectWrapper.set(proTokenizer, propValue);
}
System.out.println(metaObject.getOriginalObject());

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值