文档章节

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

crossoverJie
 crossoverJie
发布于 2017/01/19 11:48
字数 1058
阅读 623
收藏 34

1

前言

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

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

所以这里介绍一个在实际开发中还是小有用处的反射实例。

传统日志

有关反射的一些基本知识就不说了,可以自行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);
    }

非常简单,就是在保存完数据表之后再把相同的数据保存到日志表中。

但是这样有以下几个问题:

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

针对以上的情况就得需要反射这个主角来解决了。

利用反射构建日志

我们先来先来看下使用反射之后对代码所带来的改变:

    @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等对象做缓存也是很有必要的。

项目地址:https://github.com/crossoverJie/SSM.git

个人博客地址:http://crossoverjie.top

GitHub地址:https://github.com/crossoverJie

© 著作权归作者所有

crossoverJie

crossoverJie

粉丝 714
博文 97
码字总数 187484
作品 0
江北
后端工程师
私信 提问
crossoverJie/SSM

使用Idea搭建的Maven项目,会不定期更新一些在实际开发中使用的技巧,没有复杂的业务流程,更不是XXXX系统,只有一些技术的分享 目录结构 ├── SSM-API // 通用API │ ├── src/main│ ├...

crossoverJie
2018/05/09
0
0
SSM(九) 反射的实际应用 - 构建日志对象

前言 相信做Java的童鞋或多或少都听过反射,这也应该是Java从入门到进阶的必经之路。 但是在我们的实际开发中直接使用它们的几率貌似还是比较少的,()。 所以这里介绍一个在实际开发中还是...

crossoverJie
2017/01/19
0
0
漫画:如何写出更优雅的单例模式?

上一次为大家介绍了单例模式的基本概念和几种实现方式,没看过的小伙伴们可以点击下面链接: 漫画:什么是单例设计模式? 如果懒得去看也不要紧,让我们来简单回顾一下。 线程安全的懒汉型单...

bjweimengshu
2017/12/04
0
0
Java深入-框架技巧

Java 程序媛手把手教你设计模式中的撩妹神技 -- 上篇 遇一人白首,择一城终老,是多么美好的人生境界,她和他历经风雨慢慢变老,回首走过的点点滴滴,依然清楚的记得当初爱情萌芽的模样…… ...

掘金官方
2018/01/05
0
0
Server 入门后端你要学什么

好久没有更新了, 最近一个月在入门服务端的技术栈, 所以快速学了一下java, ssm框架, 这篇文章会将我的学习思路以及一些思考进行分享, 如何将一个月的学习所得通过一篇文章进行梳理, 这对我也...

Castie1
2017/11/13
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Spring Cloud 笔记之Spring cloud config client

观察者模式它的数据的变化是被动的。 观察者模式在java中的实现: package com.hxq.springcloud.springcloudconfigclient;import org.springframework.context.ApplicationListener;i...

xiaoxiao_go
今天
4
0
CentOS7.6中安装使用fcitx框架

内容目录 一、为什么要使用fcitx?二、安装fcitx框架三、安装搜狗输入法 一、为什么要使用fcitx? Gnome3桌面自带的输入法框架为ibus,而在使用ibus时会时不时出现卡顿无法输入的现象。 搜狗和...

技术训练营
今天
4
0
《Designing.Data-Intensive.Applications》笔记 四

第九章 一致性与共识 分布式系统最重要的的抽象之一是共识(consensus):让所有的节点对某件事达成一致。 最终一致性(eventual consistency)只提供较弱的保证,需要探索更高的一致性保证(stro...

丰田破产标志
今天
7
0
docker 使用mysql

1, 进入容器 比如 myslq1 里面进行操作 docker exec -it mysql1 /bin/bash 2. 退出 容器 交互: exit 3. mysql 启动在容器里面,并且 可以本地连接mysql docker run --name mysql1 --env MY...

之渊
今天
7
0
python数据结构

1、字符串及其方法(案例来自Python-100-Days) def main(): str1 = 'hello, world!' # 通过len函数计算字符串的长度 print(len(str1)) # 13 # 获得字符串首字母大写的...

huijue
今天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部