Summary
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
MetaObject
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 return; } 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.setTon("address1"); Address address2 = new Address(); address2.setTon("address2"); Student stu = new Student(); stu.setAddress(address); stu.setName("Zhang San"); stu.setAge(12); Student stu2 = new Student(); stu2.setAddress(address2); stu2.setName("Zhang San"); stu2.setAge(12); ClassRoom classRoom = new ClassRoom(); classRoom.setNo(1); ArrayList<Student> students = new ArrayList<>(); students.add(stu); students.add(stu2); classRoom.setStudentList(students); Map<String,Object> tags = new HashMap<>(); tags.put("Class One","Excellent Classes"); classRoom.setTags(tags); MetaObject metaObject = MetaObject.forObject(classRoom, new DefaultObjectFactory(), new DefaultObjectWrapperFactory(), new DefaultReflectorFactory()); Object value = metaObject.getValue("no"); System.out.println(value); Object value1 = metaObject.getValue("studentList[0].address.ton"); System.out.println(value1); Object tags1 = metaObject.getValue("tags"); System.out.println(tags1); }
Object value1 = metaObject.getValue("studentList[0].address.ton");
Let's use this to describe the logic in which it works:
- studentList[0].address.ton This gets the value, whether there are child attributes
- Yes, according to studentList[0], get the first element value in the set (stu) to MetaObject, and then get the child element, address.ton
- Make a recursive call to address.ton to get the value, and enter 2 to make a judgment until ton has no child elements
- objectWrapper.get(prop);Get, and then down is Reflection Get
ps:
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.