反射工具类MetaObject的使用

  作者:记性不好的阁主




功能:


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"));
// 如果girlFriendnullmetaObject会帮我们自动创建
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时因为没有子属性不进行递归操作,最终直接获取该属性值(张三)





相关推荐

评论 抢沙发

表情

分类选择