当前位置: 移动技术网 > IT编程>开发语言>Java > 如何优雅实现属性的动态注入

如何优雅实现属性的动态注入

2019年09月29日  | 移动技术网IT编程  | 我要评论
前言 这是在实际开发项目中遇到的一个问题。从数据库查询返回的 List\ 的集合。并且返回的列名是中文的,项目也没有使用mybatis 直接使用的jdbcTemplate. 并且字段还超级多,这样将数据转换的时候如果一个一个的注入就会让代码臭长臭长的,所以才有了动态注入。 我这里我整个思路都贴出来。 ...

前言

这是在实际开发项目中遇到的一个问题。从数据库查询返回的 list< map< string, object>> 的集合。并且返回的列名是中文的,项目也没有使用mybatis 直接使用的jdbctemplate. 并且字段还超级多,这样将数据转换的时候如果一个一个的注入就会让代码臭长臭长的,所以才有了动态注入。
我这里我整个思路都贴出来。

实例类entry

我们先建一个entry类。用于对象存储。
我这里 创建一个basedatebean 的类

@setter
@getter
public class basedatebean {

    private string  starttime;
    private string  operator;
    private string  code;
    private string  testnumber;
    private string  iphonecardcode;
    private string  samplenumber;
    private string  sampletime;
    private string  callnumber;
    private string  callstatus;
    private string  downinstantaneousspeedcard;
    private string  upinstantaneousspeedcard;
    private string  ssid;
    private string  bssid;
    private string  encrypttype;
    private string  intranetip;
    private string  externalip;
    private string  rssi;
    private string  wififrequency;
    private string  wifichannel;
    private string  baidulongitude;
    private string  baidulatitude;
    private string  originallongitude;
    private string  originallatitude;
    private string  positioningprecision;
    private string  positioningtype;
    private string  businesstype;
    private string  networktype;
    private string  speedtype;
    private string  tac;
    private string  eci;
    private string  mnc;
    private string  mcc;
    private string  rsrq;
    private string  earfcndl;
    private string  earfcnul;
    private string  frequencydl;
    private string  band;
    private string  sinr;
    private string  cdmarxlev;
    private string  evdorxlev;
    private string  earfcn;
    private string  psc;
    private string  uarfcn;
    private string  rscp;
    private string  rsrp;
    private string  imsi;
    private string  imei;
    private string  lac;
    private string  ci;
    private string  signalstrength;
    private string  snr;
    private string  pci;
    private string  nid;
    private string  bid;
    private string  sid;
    private string  cdmadbm;
    private string  cdmaecio;
    private string  evdodbm;
    private string  evdoecio;
    private string  evdosnr;
    private string  arfcn;
    private string  frequencyul;
    private string  bsic;
    private string  rxlev;
    private string  averagespeed;
    private string  updatedlongitude;
    private string  updatedlatitude;
    private string  averageupstreamrate;
    private string  averagedownstreamrate;
}

可以看到在实际项目中属性还是很多的,我这个还只是初版的,所以如果一个一个的set注入就很low了。

创建map映射

在创建好实体类后,还得创建一个静态的map 集合,将数据库的列名和我们实体类的属性名做一个一一对应。这里创建的这个map 集合是我个人愚见。没有想到更好的办法就先这样处理的。
我们创建一个basedatamap类

public  class basedatamap{
    private basedatamap(){}
    public static final map<string,string> cnenmap=new hashmap<>();
    static{
        cnenmap.put("测试开始时间","starttime");
        cnenmap.put("运营商","operator");
        cnenmap.put("编号","code");
        cnenmap.put("测试编号","testnumber");
        cnenmap.put("手机卡编号","iphonecardcode");
        cnenmap.put("采样编号","samplenumber");
        cnenmap.put("采样时间","sampletime");
        cnenmap.put("呼叫编号","callnumber");
        cnenmap.put("呼叫状态","callstatus");
        cnenmap.put("下行瞬时速度","downinstantaneousspeedcard");
        cnenmap.put("上行瞬时速度","upinstantaneousspeedcard");
        cnenmap.put("ssid","ssid");
        cnenmap.put("bssid","bssid");
        cnenmap.put("加密类型","encrypttype");
        cnenmap.put("内网ip","intranetip");
        cnenmap.put("外网ip","externalip");
        cnenmap.put("rssi","rssi");
        cnenmap.put("wifi频率","wififrequency");
        cnenmap.put("wifi信道","wifichannel");
        cnenmap.put("百度经度","baidulongitude");
        cnenmap.put("百度纬度","baidulatitude");
        cnenmap.put("原始经度","originallongitude");
        cnenmap.put("原始纬度","originallatitude");
        cnenmap.put("定位精度","positioningprecision");
        cnenmap.put("定位类型","positioningtype");
        cnenmap.put("数据业务类型","businesstype");
        cnenmap.put("网络类型","networktype");
        cnenmap.put("速度类型","speedtype");
        cnenmap.put("tac","tac");
        cnenmap.put("eci","eci");
        cnenmap.put("mnc","mnc");
        cnenmap.put("mcc","mcc");
        cnenmap.put("rsrq","rsrq");
        cnenmap.put("earfcn dl","earfcndl");
        cnenmap.put("earfcn ul","earfcnul");
        cnenmap.put("frequency dl","frequencydl");
        cnenmap.put("band","band");
        cnenmap.put("sinr","sinr");
        cnenmap.put("cdma rxlev","cdmarxlev");
        cnenmap.put("evdo rxlev","evdorxlev");
        cnenmap.put("earfcn","earfcn");
        cnenmap.put("psc","psc");
        cnenmap.put("uarfcn","uarfcn");
        cnenmap.put("rscp","rscp");
        cnenmap.put("rsrp","rsrp");
        cnenmap.put("imsi","imsi");
        cnenmap.put("imei","imei");
        cnenmap.put("lac","lac");
        cnenmap.put("ci","ci");
        cnenmap.put("信号强度","signalstrength");
        cnenmap.put("snr","snr");
        cnenmap.put("pci","pci");
        cnenmap.put("nid","nid");
        cnenmap.put("bid","bid");
        cnenmap.put("sid","sid");
        cnenmap.put("cdma dbm","cdmadbm");
        cnenmap.put("cdma ecio","cdmaecio");
        cnenmap.put("evdo dbm","evdodbm");
        cnenmap.put("evdo ecio","evdoecio");
        cnenmap.put("evdo snr","evdosnr");
        cnenmap.put("arfcn","arfcn");
        cnenmap.put("frequency ul","frequencyul");
        cnenmap.put("bsic","bsic");
        cnenmap.put("rxlev","rxlev");
        cnenmap.put("速率","averagespeed");
        cnenmap.put("更正后经度","updatedlongitude");
        cnenmap.put("更正后纬度","updatedlatitude");
        cnenmap.put("上行平均速率","averageupstreamrate");
        cnenmap.put("下行平均速率","averagedownstreamrate");
    }
}

可以看到就是一个动态的map。

映射类

接下来就是核心代码啦。我们创建一个reflecthelper类

@slf4j
public class reflecthelper {

    private class cls;
    /**
     * 传过来的对象
     */
    private object obj;
    private hashtable<string, method> getmethods = null;
    private hashtable<string, method> setmethods = null;
    public reflecthelper(object o) {
        obj = o;
        initmethods();
    }
    public void initmethods() {
        getmethods = new hashtable<>();
        setmethods = new hashtable<>();
        cls = obj.getclass();
        method[] methods = cls.getmethods();
        // 定义正则表达式,从方法中过滤出getter / setter 函数.
        string gs = "get(\\w+)";
        pattern getm = pattern.compile(gs);
        string ss = "set(\\w+)";
        pattern setm = pattern.compile(ss);
        // 把方法中的"set" 或者 "get" 去掉,$1匹配第一个
        string rapl = "$1";
        string param;
        for (int i = 0; i < methods.length; ++i) {
            method m = methods[i];
            string methodname = m.getname();
            if (pattern.matches(gs, methodname)) {
                param = getm.matcher(methodname).replaceall(rapl).tolowercase();
                getmethods.put(param, m);
            } else if (pattern.matches(ss, methodname)) {
                param = setm.matcher(methodname).replaceall(rapl).tolowercase();
                setmethods.put(param, m);
            }
        }
    }
    public boolean setmethodvalue(string property,object object) {
        method m = setmethods.get(property.tolowercase());
        if (m != null) {
            try {
                // 调用目标类的setter函数
                m.invoke(obj, object);
                return true;
            } catch (exception ex) {
                ex.printstacktrace();
                return false;
            }
        }
        return false;
    }
}

上面代码可以看到其实也就两个方法setmethodvalue 和initmethods 。
initmethods 方法是在实例化 reflecthelper 这个类的时候执行的,主要的工作就是找到我们需要动态注入实例类的get 和set 方法。而setmethodvalue 方法就是给这个属性赋值的。
# 实现方法
现在准备工作做好了,怎么使用呢?
private list<basedatebean> getbasedatebean(list<map<string, object>> maplist){ list<basedatebean> list=new arraylist<>(); if(maplist==null||maplist.isempty()){ return list; } basedatebean basedatebean; for(map<string, object> map:maplist){ basedatebean=new basedatebean(); for(map.entry<string, object> entry : map.entryset()){ string mapkey = entry.getkey(); log.info(mapkey); reflecthelper reflecthelper = new reflecthelper(basedatebean); log.info(basedatamap.cnenmap.get(mapkey)); string value=entry.getvalue()==null?constantpool.separatornull:entry.getvalue().tostring(); log.info(value); if(entry.getvalue()!=null){ reflecthelper.setmethodvalue(basedatamap.cnenmap.get(mapkey),string.valueof(entry.getvalue())); } } list.add(basedatebean); } return list; }
遍历list 集合中的map,动态的将属性值注入到实体类中。

# 番外
我这里是适合我业务开发设计的思路,给大家借鉴参考。

欢迎大家关注个人公众号 "程序员爱酸奶"

分享各种学习资料,包含java,linux,大数据等。资料包含视频文档以及源码,同时分享本人及投递的优质技术博文。

如果大家喜欢记得关注和分享哟❤
file

如您对本文有疑问或者有任何想说的,请点击进行留言回复,万千网友为您解惑!

相关文章:

验证码:
移动技术网