功能:
1、直接操作属性
2、操作子属性
3、自动创建属性对象
4、自动查找属性名,支持下划线转驼峰
5、基于索引访问数组
6、基于key访问map
使用demo:
Person Bean:
package com.laoxu.mybatis.modal;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
public class Person implements Serializable {
private String id;
private String name;
private String sex;
private String age;
private String createTime;
public Person getGirlFriend() {
return girlFriend;
}
public void setGirlFriend(Person girlFriend) {
this.girlFriend = girlFriend;
}
public List<Person> getFriends() {
return friends;
}
public void setFriends(List<Person> friends) {
this.friends = friends;
}
public Map<String, String> getOther() {
return other;
}
public void setOther(Map<String, String> other) {
this.other = other;
}
private Person girlFriend;
private List<Person> friends;
private Map<String, String> other;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public String getCreateTime() {
return createTime;
}
public void setCreateTime(String createTime) {
this.createTime = createTime;
}
@Override
public String toString() {
return "Person{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
", sex='" + sex + '\'' +
", age='" + age + '\'' +
", createTime='" + createTime + '\'' +
'}';
}
}
使用demo:
package com.laoxu.mybatis.executor.metaObject;
import com.laoxu.mybatis.modal.Person;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.session.Configuration;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class Test {
public static void main(String[] args) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
// test1();
// test2();
// test3();
// test4();
test5();
// test6();
}
// 原始反射方式
private static void test1() throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
Person p = new Person();
p.setSex("男");
Object person = p;
Method getSex = person.getClass().getDeclaredMethod("getSex");
Object invoke = getSex.invoke(person);
System.out.println(invoke);
}
// metaObject工具类方式
private static void test2() {
// 装饰器模式
Object person = new Person();
Configuration configuration = new Configuration();
// 装饰
MetaObject metaObject = configuration.newMetaObject(person);
metaObject.setValue("sex", "女");
System.out.println(metaObject.getValue("sex"));
Person 我 = (Person) person;
System.out.println(我.getSex());
}
// metaObject工具类方式
private static void test3() {
// 装饰器模式
Object person = new Person();
Configuration configuration = new Configuration();
// 装饰
MetaObject metaObject = configuration.newMetaObject(person);
metaObject.setValue("girlFriend.name", "女朋友");
metaObject.setValue("girlFriend.sex", "女");
System.out.println(metaObject.getValue("girlFriend.name"));
System.out.println(metaObject.getValue("girlFriend.sex"));
// 如果girlFriend为null,metaObject会帮我们自动创建
Person 我 = (Person) person;
System.out.println(我.getGirlFriend().getName());
System.out.println(我.getGirlFriend().getSex());
}
// metaObject工具类方式
private static void test4() {
// 装饰器模式
Object person = new Person();
Configuration configuration = new Configuration();
// 装饰
MetaObject metaObject = configuration.newMetaObject(person);
// 使用驼峰查找属性
String property = metaObject.findProperty("girlFriend.create_time", true);
System.out.println(property);
}
// metaObject工具类方式 【列表】
private static void test5() {
//直接操作属性
//操作子属性
//自动创建属性对象
//自动查找属性名,支持下划线转驼峰
//基于索引访问数组
// 装饰器模式
Object person = new Person();
Configuration configuration = new Configuration();
// 装饰
MetaObject metaObject = configuration.newMetaObject(person);
// 数组不能自动创建
List<Person> friends = new ArrayList<>();
Person friend1 = new Person();
friend1.setName("张三");
friend1.setSex("男");
Person friend2 = new Person();
friend2.setName("李四");
friend2.setSex("男");
Person friend3 = new Person();
friend3.setName("王五");
friend3.setSex("女");
friends.add(friend1);
friends.add(friend2);
friends.add(friend3);
metaObject.setValue("friends", friends);
Object value1 = metaObject.getValue("friends[0].name");
Object value2 = metaObject.getValue("friends[1].name");
Object value3 = metaObject.getValue("friends[2].name");
System.out.println(value1);
System.out.println(value2);
System.out.println(value3);
Person p = (Person) person;
for (Person friend : p.getFriends()) {
System.out.println(friend.getName());
System.out.println(friend.getSex());
}
}
// metaObject工具类方式 【字典】
private static void test6() {
//直接操作属性
//操作子属性
//自动创建属性对象
//自动查找属性名,支持下划线转驼峰
//基于索引访问数组
// 装饰器模式
Object person = new Person();
Configuration configuration = new Configuration();
// 装饰
MetaObject metaObject = configuration.newMetaObject(person);
metaObject.setValue("other", new HashMap<>());
metaObject.setValue("other[height]", "1.7米");
metaObject.setValue("other[weight]", "60kg");
Person p = (Person) person;
System.out.println(p.getOther().get("height"));
System.out.println(p.getOther().get("weight"));
}
}
完整解析流程图:
源码解析过程:
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);
}
}
1、创建分词器对表达式进行分词
PropertyTokenizer prop = new PropertyTokenizer(name);
以delim为边界截取想要的分词
继续调用getValue方法
此时没有子属性,直接获取属性值
获取到对象Person
重新去包装对象Person
metaValue是一个包装了Person对象的MetaObject
此时获取Person.name时因为没有子属性不进行递归操作,最终直接获取该属性值(张三)