背景介绍

短信平台需要支持多种短信的发送,短信文案皆不相同,假设有以下类

@Data
public abstract class MsgBase {public static final String ALIBABA_GROUP  = "阿里巴巴集团";public static final String ANT_GROUP  = "蚂蚁集团";/*** 接收人手机号*/private String receivePhone;/*** 接收人姓名*/private String name;/*** 咨询电话*/private String consultationPhone;/*** 集团名称*/private String groupName;/*** 内容模版* 模版内容中的变量使用${}引用,其中变量名要在成员变量中*/private String template;/*** 发送*/public void send() {// 替换模版中的变量replaceTemplate();// 省略发送 。。。}/*** 替换模版*/private void replaceTemplate() {// 把所有属性压到Map中Map<String, Object> fieldParamMap = Maps.newConcurrentMap();try {for (Field field : this.getClass().getDeclaredFields()) {fieldParamMap.put(field.getName(), BeanUtils.getProperty(this, field.getName()));}for (Field field : this.getClass().getSuperclass().getDeclaredFields()) {fieldParamMap.put(field.getName(), BeanUtils.getProperty(this, field.getName()));}// 变量替换 ...} catch (Exception e) {throw new RuntimeException("send message Error!", e);}}
}
/*** 充值通知短信*/
@Data
public class RechargeNoticeMsgBase extends MsgBase {/*** 充值日期*/private String date;/*** 充值金额*/private String amount;
}
/*** 快递收获通知短信*/
@Data
public class ExpressHarvestNoticeMsgBase extends MsgBase {/*** 取件码*/private String code;/*** 快递柜*/private String expressDeliveryCabinet;
}

在不同场景下会构造不同的短信,一开始短信中没有集团名称,后来才有的需求,后面同学这考虑到集团名称只有几个,因此在Base类中定义了几个静态常量,以供子类共享,但是却带来了问题:

public class MsgTestMain {public static void main(String[] args) {RechargeNoticeMsgBase msg = new RechargeNoticeMsgBase();msg.setAmount("100");msg.setDate("2020-12-20");msg.setGroupName(MsgBase.ALIBABA_GROUP);msg.setConsultationPhone("13123457890");msg.setTemplate("【companyName】 ${name} 您好,您在${date}充值了${amount}元,如有疑问请联系 ${consultationPhone}");msg.setReceivePhone("13112345678");msg.setName("张三");msg.send();}
}

运行测试类,发现如下异常:

Exception in thread "main" java.lang.RuntimeException: send message Error!at beanutils.MsgBase.replaceTemplate(MsgBase.java:68)at beanutils.MsgBase.send(MsgBase.java:49)at beanutils.MsgTestMain.main(MsgTestMain.java:14)
Caused by: java.lang.NoSuchMethodException: Unknown property 'ALIBABA_GROUP' on class 'class beanutils.RechargeNoticeMsgBase'at org.apache.commons.beanutils.PropertyUtilsBean.getSimpleProperty(PropertyUtilsBean.java:1270)at org.apache.commons.beanutils.PropertyUtilsBean.getNestedProperty(PropertyUtilsBean.java:809)at org.apache.commons.beanutils.BeanUtilsBean.getNestedProperty(BeanUtilsBean.java:711)at org.apache.commons.beanutils.BeanUtilsBean.getProperty(BeanUtilsBean.java:737)at org.apache.commons.beanutils.BeanUtils.getProperty(BeanUtils.java:380)at beanutils.MsgBase.replaceTemplate(MsgBase.java:64)

也就是在执行 BeanUtils.getProperty(“ALIBABA_GROUP”)发生异常,当前实例没有这个Field!这是为什么呢?BeanUtils内部是怎么实线的呢?

原理说明

跟踪代码:

org.apache.commons.beanutils.BeanUtils#getProperty
-> org.apache.commons.beanutils.BeanUtilsBean#getProperty
-> org.apache.commons.beanutils.BeanUtilsBean#getNestedProperty
-> org.apache.commons.beanutils.PropertyUtilsBean#getNestedProperty
-> org.apache.commons.beanutils.PropertyUtilsBean#getSimpleProperty
...
-> org.apache.commons.beanutils.PropertyUtilsBean#getPropertyDescriptors(java.lang.Class)
-> java.beans.Introspector#getBeanInfo(java.lang.Class<?>)
-> java.beans.Introspector#getBeanInfo()
-> java.beans.Introspector#getTargetPropertyInfo

getTargetPropertyInfo方法部分代码如下图:

其中getPublicDeclareMethods方法如下:

通过以上代码可知BeanUtils获取Field并未通过java.lang.Class#getFields来获取,而是通过getMethods来获取,这个方法返回的是public的方法,并且排除了静态方法,因此想通过BeanUtils获取静态属性是不行的!

解决方案

  • 定义一个常量类,避免使用静态变量
  • 修改replaceTemplae,通过Modifier.isStatic方法判断是否是静态变量,如果是将其排除

BeanUtils getProperty的一个坑相关推荐

  1. 最近,我在Spring的BeanUtils踩了不少坑

    点击关注公众号,实用技术文章及时了解 来源:www.jianshu.com/p/357b55852efc 背景 最近项目中在和第三方进行联调一个接口,我们这边发送http请求给对方,然后接收对方的回应 ...

  2. 困扰多日的C#调用Haskell问题竟然是Windows的一个坑

    最近一直被C#调用Haskell时的"尝试读取或写入受保护的内存"问题所困扰(详见C#调用haskell遭遇Attempted to read or write protected ...

  3. SAP WM LT10事务代码的一个坑?

    SAP WM LT10事务代码的一个坑? 执行事务代码LT10,试图将storage type SAM下物料库存的几个SU转入同一个货架上.Storage type SAM有启用SUM功能的. 执行, ...

  4. mysql div 没有小数,mysql order by limit 的一个坑

    mysql order by limit 的一个坑 分页查询的时候遇到的坑: 发现的问题: 对单个无索引的字段进行排序后limit .发现当被排序字段有相同值时并且在limit范围内,取的值并不是正常 ...

  5. 移动端开发碰到一个坑

    移动端开发真是不断踩坑,今天在做一个移动端的组件,又发现了一个坑,记录到日志里面,做个记录,以便以后再遇到这个问题有个记录可以参考. 在ios中的chrome浏览器中,手指从屏幕上方移动出屏幕(一定要 ...

  6. centos 升级mysql_CentOS 7下升级MySQL5.7.23的一个坑

    发现CentOS 7下升级MySQL5.7.23的一个坑,以前面升级到MySQL 5.7.23的一个集群为例 在我们环境下打开文件描述符个数的参数open_files_limit在MySQL 5.6. ...

  7. 0705 - 说说 NSPopover 的一个坑

    今天开发 iTips,遇到一个很诡异的问题:NSOutlineView 中的 NSTableCellView 中的 NSTextField,始终有一个背景色,无论怎么设置都无法去掉.如下图中左侧部分所 ...

  8. nodejs request module里的json参数的一个坑

    今天工作的时候遇到一个坑,在客户端用nodejs给服务器发送HTTP请求,服务器老是报错:In the context of Data Services an unknown internal ser ...

  9. 记录我开发工作中遇到HTTP跨域和OPTION请求的一个坑

    我通过这篇文章把今天工作中遇到的HTTP跨域和OPTION请求的一个坑记录下来. 场景是我需要在部署在域名a的Web应用里用JavaScript去消费一个部署在域名b的服务器上的服务.域名b上的服务也 ...

最新文章

  1. 深度学习需要掌握的 13 个概率分布(附代码)
  2. 两位院士同时受聘,山东大学再添强援
  3. 【论文解读】KDD20 | 图神经网络在生物医药领域的应用
  4. android 富文本框架_五种JavaScript富文本编辑器,总有一款适合你
  5. CentOS linux7 设置开机启动服务
  6. HookProc 和 CallNextHookEx
  7. 12v驱动光耦用多大的电阻_倍思10000mAh PD快充充电宝拆解,内置多合一双向快充芯片...
  8. Linux中vectormath无法通过pip安装的解决办法
  9. ThinkPHP胜出Laravel 近4倍,主流框架性能测试
  10. 织梦响应式酒店民宿住宿类网站织梦模板(自适应手机端)
  11. ShadowGun 的学习笔记 - GodRays
  12. re库中group(), groups(), groupdict() 用法
  13. 【小应用】社交距离检测
  14. 前端HTML、CSS学习完整笔记(中下篇)
  15. excel计数连续负数(正数)
  16. 【数据分析 —— 认识数据】
  17. CUDA安装 + tensorflow gpu版本出现的问题:Not creating XLA devices, tf_xla_enable_xla_devices not set
  18. cad直线和圆弧倒角不相切_CAD圆角、倒角分不清?详细讲解CAD圆角与倒角对象的区别和技巧...
  19. 迅雷、QQ旋风-链接自动转换(Download link conversion)
  20. 如何开发一款ios应用程序

热门文章

  1. java 计算弧度_java中角度或弧度的计算
  2. java 区分缺陷Defects/感染Infections/失败Failure
  3. python获取变量名
  4. PHP PHPExcel 下拉 让其只能在其下拉的分表隐藏并设置解锁密码
  5. Jin,don't ever do that
  6. 3.文字属性 font
  7. Pytorch中scatter与gather操作
  8. 守护线程是什么?守护线程和非守护线程的区别是?守护线程的作用是?
  9. Rubymine 无法Debug的方法
  10. React之Hook(六)——自定义 Hook