SSM(九) 反射的实际应用 - 构建日志对象

前言

相信作Java的童鞋或多或少都听过反射,这也应该是Java从入门到进阶的必经之路。java

可是在咱们的实际开发中直接使用它们的概率貌似仍是比较少的,(除了造轮子或者是Spring Mybatis这些框架外)。git

因此这里介绍一个在实际开发中仍是小有用处的反射实例。github

传统日志

有关反射的一些基本知识就不说了,能够自行Google,也能够看下反射入门数据库

日志相信你们都不陌生,在实际开发中一些比较敏感的数据表咱们须要对它的每一次操做都记录下来。缓存

先来看看传统的写法:框架

@Test
    public void insertSelective() throws Exception {

        Content content = new Content() ;
        content.setContent("asdsf");
        content.setCreatedate("2016-12-09");
        contentService.insertSelective(content) ;

        ContentLog log = new ContentLog();
        log.setContentid(content.getContentid());
        log.setContent("asdsf");
        log.setCreatedate("2016-12-09");
        contentLogService.insertSelective(log);
    }复制代码

很是简单,就是在保存完数据表以后再把相同的数据保存到日志表中。工具

可是这样有如下几个问题:spa

  • 若是数据表的字段较多的话,好比几百个。那么日志表的setter()方法就得写几百次,还得是都写对的状况下。
  • 若是哪天数据表的字段发生了增长,那么每一个写日志的地方都得增长该字段,提升了维护的成本。

针对以上的状况就得须要反射这个主角来解决了。日志

利用反射构建日志

咱们先来先来看下使用反射以后对代码所带来的改变:code

@Test
    public void insertSelective2() throws Exception {
        Content content = new Content();
        content.setContent("你好");
        content.setContentname("1");
        content.setCreatedate("2016-09-23");

        contentService.insertSelective(content);

        ContentLog log = new ContentLog();
        CommonUtil.setLogValueModelToModel(content, log);
        contentLogService.insertSelective(log);
    }复制代码

一样的保存日志,无论多少字段,只须要三行代码便可解决。
并且就算以后字段发生改变写日志这段代码仍然不须要改动。

其实这里最主要的一个方法就是CommonUtil.setLogValueModelToModel(content, log);

来看下是如何实现的;

/** * 生成日志实体工具 * * @param objectFrom * @param objectTo */
    public static void setLogValueModelToModel(Object objectFrom, Object objectTo) {
        Class<? extends Object> clazzFrom = objectFrom.getClass();
        Class<? extends Object> clazzTo = objectTo.getClass();

        for (Method toSetMethod : clazzTo.getMethods()) {
            String mName = toSetMethod.getName();
            if (mName.startsWith("set")) {
                //字段名
                String field = mName.substring(3);

                //获取from 值
                Object value;
                try {
                    if ("LogId".equals(field)) {
                        continue;
                    }
                    Method fromGetMethod = clazzFrom.getMethod("get" + field);
                    value = fromGetMethod.invoke(objectFrom);

                    //设置值
                    toSetMethod.invoke(objectTo, value);
                } catch (NoSuchMethodException e) {
                    throw new RuntimeException(e);
                } catch (InvocationTargetException e) {
                    throw new RuntimeException(e);
                } catch (IllegalAccessException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }复制代码

再使用以前咱们首先须要构建好主的数据表,而后new一个日志表的对象。

setLogValueModelToModel()方法中:

  • 分别得到数据表和日志表对象的类类型。
  • 获取到日志对象的全部方法集合。
  • 遍历该集合,并拿到该方法的名称。
  • 只取其中set开头的方法,也就是set方法。由于咱们须要在循环中为日志对象的每个字段赋值。
  • 以后截取方法名称得到具体的字段名称。
  • 用以前截取的字段名称,经过getMethod()方法返回数据表中的该字段的getter方法。
  • 至关于执行了String content = content.getContent();
  • 执行该方法得到该字段具体的值。
  • 利用当前循环的setter方法为日志对象的每个字段赋值。
  • 至关于执行了log.setContent("asdsf");

其中字段名称为LogId时跳出了当前循环,由于LogId是日志表的主键,是不须要赋值的。

当循环结束时,日志对象也就构建完成了。以后只须要保存到数据库中便可。

总结

反射实际上是很是耗资源的,再使用过程当中仍是要慎用。
其中对method、field、constructor等对象作缓存也是颇有必要的。

项目地址:github.com/crossoverJi…

我的博客地址:crossoverjie.top

GitHub地址:github.com/crossoverJi…

相关文章
相关标签/搜索