反射结合泛型实现任意对象的创建
作者:互联网
一、反射及泛型
反射可以通过Class创建对象,而泛型则可以创建程序模板。
二、Mybatis中的应用
2.1定义mapper
定义一个通用的sql,允许传入表名table,以及查询条件where,返回值List<Map<String,Object>>。
public interface CommonMapper {
@Select("select * from ${table} where ${where}")
List<Map<String,Object>> GetList(@Param(value="table") String table, @Param(value="where") String where);
}
2.1定义service
我们使用通配符接收Class,然后通过Class.getDeclaredConstructor().newInstance()创建一个新对象,然后使用 BeanUtils.populate()填充对象。其实我们这里也就是相当于实现了Mybatis-plus自带的功能,不建议这样做,因为反射的消耗也挺大的。
public <E> List<E> GetList(Class<?> resultType, String where) throws Exception {
ArrayList<E> results = new ArrayList<E>();
ConvertUtils.register(new MyConverter(), LocalDateTime.class);
List<Map<String,Object>>result= commonMapper.GetList(resultType.getSimpleName(),where);
for(Map<String,Object> m:result){
E e= (E) resultType.getDeclaredConstructor().newInstance();
m=formateMapKey(m);
BeanUtils.populate(e, m);
results.add(e);
}
return results;
}
/**
* 将数据库返回的键值修改为符合java Bean的规范,前两个字母要么大写要么小写
* @param orgMap
* @return
*/
public Map<String, Object> formateMapKey(Map<String, Object> orgMap) {
Map<String, Object> resultMap = new HashMap<>();
if (orgMap == null || orgMap.isEmpty()) {
return resultMap;
}
Set<String> keySet = orgMap.keySet();
for (String key : keySet) {
String newKey= formatJavaBeanName(key);
resultMap.put(newKey, orgMap.get(key));
}
return resultMap;
}
三、WebService中的应用
3.1 解析对象构建xml
传入对象T,获取到CLass对象,再拿到相应的Field对象,遍历每个属性,获取到相应的get方法然后获取属性值,最后组装xml字符串。获取属性值,还可以使用Field.get方法。
public static <T> String Analysis(T m_Value) throws Exception {
String m_XML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
m_XML += "<DBSET>\n";
m_XML += "<ROW>\n";
Field[] fields = m_Value.getClass().getDeclaredFields();
for (var property : fields) {
//获取属性的名字
String name = property.getName();
//将属性名字的首字母大写
name = name.replaceFirst(name.substring(0, 1), name.substring(0, 1).toUpperCase());
//整合出 getId() 属性这个方法
Method m = m_Value.getClass().getMethod("get" + name);
//调用这个整合出来的get方法,强转成自己需要的类型
Object obj = m.invoke(m_Value);
if (obj == null) {
obj = "";
}
m_XML += "<" + property.getName() + ">";
switch (property.getType().getName()) {
case "LocalDateTime":
m_XML += DateUtil.format((LocalDateTime) obj, "yyyy-MM-dd HH:mm:s");
break;
default:
m_XML += obj.toString();
break;
}
m_XML += "</" + property.getName() + ">\n";
}
m_XML += "</ROW>";
m_XML += "</DBSET>";
logger.info(m_XML);
return m_XML;
}
3.1 解析XML字符串转换为对象
特别注意使用到了PropertyDescriptor
public static <T> T ResolveXML(T o, String sXml) throws Exception {
String Result = "";
Document document = DocumentHelper.parseText(sXml);
Element rootElement = document.getRootElement();
// rootElement = rootElement.element("DBSET");
rootElement = rootElement.element("ROW");
Class cls = o.getClass();
Field[] fields = cls.getDeclaredFields();
for (var property : fields) {
//获取属性的名字
String columnName = property.getName();
Element node = rootElement.element(columnName);
if (node == null || StringUtils.isBlank(node.getText()))
continue;
Result = node.getTextTrim();
//使用反射或者内省,根据数据库表和实体的对应关系,完成封装
PropertyDescriptor propertyDescriptor = new PropertyDescriptor(columnName, cls);
Method writeMethod = propertyDescriptor.getWriteMethod();
writeMethod.invoke(o, Result);
}
return o;
}
标签:XML,反射,return,String,任意,rootElement,泛型,where,name 来源: https://blog.csdn.net/jiqiren1994/article/details/118877745