java反射的应用

传统日志


有关反射的一些基本知识就不说了,可以自行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()方法就得写几百次,还得是都写对的情况下。

  • 如果哪天数据表的字段发生了增加,那么每个写日志的地方都得增加该字段,提高了维护的成本。

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

利用反射构建日志


public void insertSelective() throws Exception{
        Content content = new Content;
        content.setContent("asdsf");
        content.setCreateDate(new Date());
        contentService.insertSelective(content) ;

        ContentLog log = new ContentLog();
        CommonUtil.setLogValueModelToModel(content,log);
        contentLogService.insertSelective(log);
}

同样的保存日志,不管多少字段,只需要三行代码即可解决。
而且就算之后字段发生改变写日志这段代码仍然不需要改动。

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

来看下是如何实现的:

package org.java;

import java.lang.reflect.Method;

/**
 * @author yangkun
 * @date 2021-04-07
 */
public class CommonUtil {

    public static void setLogValueModelToModel(Object objectFrom, Object objectTo) {
        Class<? extends Object> clazzFrom = objectFrom.getClass();
        Class<? extends Object> clazzTo = objectTo.getClass();

        Method[] methods = clazzTo.getMethods();
        for(Method toSetMethod : methods){
            String name = toSetMethod.getName();
            if(name.startsWith("set")){
                //字段名
                String field = name.substring(3);
                //获取from的值
                Object fieldValue = null;
                try{
                    if ("LogId".equals(field)) {
                        continue;
                    }
                    Method fromGetMethod = clazzFrom.getMethod("get" + field);
                    fieldValue = fromGetMethod.invoke(objectFrom);

                    //设置值
                    toSetMethod.invoke(objectTo,fieldValue);
                }catch(Exception e){
                    e.printStackTrace();
                }
            }
        }
    }
}

再使用之前我们首先需要构建好主的数据表,然后new一个日志表的对象。

在setLogValueModelToModel()方法中:

  • 分别获得数据表和日志表对象的类类型。

  • 获取到日志对象的所有方法集合。

  • 遍历该集合,并拿到该方法的名称。

  • 只取其中set开头的方法,也就是set方法。因为我们需要在循环中为日志对象的每一个字段赋值。

  • 之后截取方法名称获得具体的字段名称。

  • 用之前截取的字段名称,通过getMethod()方法返回数据表中的该字段的getter方法。

  • 相当于执行了String content = content.getContent();

  • 执行该方法获得该字段具体的值。

  • 利用当前循环的setter方法为日志对象的每一个字段赋值。

  • 相当于执行了log.setContent(“asdsf”);

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值