MetaObject mybatis reflector system


MetaObject is a reflection tool class for Mybatis that is highly encapsulated, gets values based on attributes, sets values, and supports the nesting structure of objects
objectWrapper is to get the property value of the current object and does not support object nesting
MetaClass supports getting child attributes
Reflector simply uses reflection to get or set a value, which is equivalent to encapsulating one layer at a time. Let's look from top to bottom


Although we're mainly looking at MetaOject today, there's nothing to look at just this category, combined with ObjectWrapper

 //Original Object
  private final Object originalObject;
  //Packaging Object
  private final ObjectWrapper objectWrapper;
  private final ObjectFactory objectFactory;
  private final ObjectWrapperFactory objectWrapperFactory;
  private final ReflectorFactory reflectorFactory;

A few attributes we are mainly concerned with objectWrapper, the other factory classes are all default, and the code is basically nothing;

private MetaObject(Object object, ObjectFactory objectFactory, ObjectWrapperFactory objectWrapperFactory, ReflectorFactory reflectorFactory) {
    this.originalObject = object;
    this.objectFactory = objectFactory;
    this.objectWrapperFactory = objectWrapperFactory;
    this.reflectorFactory = reflectorFactory;

    if (object instanceof ObjectWrapper) {  //The original object itself is a wrapper class
      this.objectWrapper = (ObjectWrapper) object;
    } else if (objectWrapperFactory.hasWrapperFor(object)) {  //The default is to return fase unless we define objectWrapperFactory ourselves
      this.objectWrapper = objectWrapperFactory.getWrapperFor(this, object);
    } else if (object instanceof Map) {  // The original class belongs to map
      this.objectWrapper = new MapWrapper(this, (Map) object);
    } else if (object instanceof Collection) { // The original class belongs to a collection
      this.objectWrapper = new CollectionWrapper(this, (Collection) object);
    } else {  //Common bean objects
      this.objectWrapper = new BeanWrapper(this, object);

Privatization of construction methods

public static MetaObject forObject(Object object, ObjectFactory objectFactory, ObjectWrapperFactory objectWrapperFactory, ReflectorFactory reflectorFactory) {
    if (object == null) {
      return SystemMetaObject.NULL_META_OBJECT;
    } else {
      return new MetaObject(object, objectFactory, objectWrapperFactory, reflectorFactory);

Get a MetaObject object from this forObject and return a SystemMetaObject if the original object passed in is null

public Object getValue(String name) {
    PropertyTokenizer prop = new PropertyTokenizer(name);
    if (prop.hasNext()) {
      MetaObject metaValue = metaObjectForProperty(prop.getIndexedName());
      if (metaValue == SystemMetaObject.NULL_META_OBJECT) {
        return null;
      } else {
        return metaValue.getValue(prop.getChildren());
    } else {
      return objectWrapper.get(prop);

  public void setValue(String name, Object value) {
    PropertyTokenizer prop = new PropertyTokenizer(name);
    if (prop.hasNext()) {
      MetaObject metaValue = metaObjectForProperty(prop.getIndexedName());
      if (metaValue == SystemMetaObject.NULL_META_OBJECT) {
        if (value == null) {
          // don't instantiate child path if value is null
        } else {
          metaValue = objectWrapper.instantiatePropertyValue(name, prop, objectFactory);
      metaValue.setValue(prop.getChildren(), value);
    } else {
      objectWrapper.set(prop, value);

The two core methods, followed by the process

MetaObject Run Logic

This is an example of the teacher's use in Teaching

I've written an example: ps: It's more useful to debug yourself than to look at this picture:

public static void main(String[] args) {
    Address address = new Address();
    Address address2 = new Address();

    Student stu = new Student();
    stu.setName("Zhang San");

    Student stu2 = new Student();
    stu2.setName("Zhang San");

    ClassRoom classRoom = new ClassRoom();
    ArrayList<Student> students = new ArrayList<>();
    Map<String,Object> tags = new HashMap<>();
    tags.put("Class One","Excellent Classes");

    MetaObject metaObject = MetaObject.forObject(classRoom, new DefaultObjectFactory(), new DefaultObjectWrapperFactory(), new DefaultReflectorFactory());

    Object value = metaObject.getValue("no");

    Object value1 = metaObject.getValue("studentList[0].address.ton");

    Object tags1 = metaObject.getValue("tags");


Object value1 = metaObject.getValue("studentList[0].address.ton");
Let's use this to describe the logic in which it works:

  1. studentList[0].address.ton This gets the value, whether there are child attributes
  2. Yes, according to studentList[0], get the first element value in the set (stu) to MetaObject, and then get the child element, address.ton
  3. Make a recursive call to address.ton to get the value, and enter 2 to make a judgment until ton has no child elements
  4. objectWrapper.get(prop);Get, and then down is Reflection Get

studentList[0] When getting the value of the first element, first use name to get the collection of this attribute, then use indexedName to get the number of elements, so you can get the value of the number of elements in the collection directly

public class PropertyTokenizer implements Iterator<PropertyTokenizer> {
  //Property Name
  private String name;
  //Property Nameāž•The index is primarily a collection attribute eg: user[0]
  private final String indexedName;

Originally, I thought about a more complete process, which was too complex and confusing, and less than half of it was debug.

Tags: Java html unit testing

Posted on Mon, 11 Oct 2021 12:39:41 -0400 by rizi