就改了get,却不让我set?——Java内省机制的神奇行为举止一例
【相关类库】org.apache.commons.beanutils.BeanUtils,提供对Java反射和自省API的包装,其中底层使用到了Java的内省方法。
【内省的一般应用形式】通过类Introspector 来获取某个对象的 BeanInfo 信息,然后通过 BeanInfo 来获取属性的描述器(PropertyDescriptor),通过这个属性描述器就可以获取某个属性对应的 getter/setter方法,然后我们就可以通过反射机制来调用这些方法。
【代码使用】Introspector.getBeanInfo(Class<?> beanClass);拿BeanInfo对象。
【例子】例如一个price属性,
1、定义 private Long price; // 价格
2、set方法
public void setPrice(Long price) {
this.price = price;
}
3、get方法
public String getPrice() {
return null == price ? null : StringUtil.priceToStr(price);
}
则通过内省只会拿到get方法。
【原理和注意事项】getBeanInfo()方法(返回GenericBeanInfo),其中有getTargetPropertyInfo(),会通过getPublicDeclaredMethods(beanClass);找出所有的get、set方法以PropertyDescriptor存储在list(通常长度为2),然后通过hashmap(属性名,list)暂存;
然后通过processPropertyDescriptors()进行筛选和合并,
(这个方法官方注释 Populates the property descriptor table by merging the lists of Property descriptors.)
其中会判断get方法的返回值和set方法的参数类型是否assignable,若不一致则以get方法为准,认为只有get方法符合要求。
然后存储在Introspector的properties当中,供GenericBeanInfo的构造方法调用。
之后BeanInfo对外暴露getPropertyDescriptors(),取其中的properties。
注:java.beans.Introspector当中,Introspector是public的,还有一个
GenericBeanInfo是包级可见的类(带蓝三角)。
官方注释
* Package private implementation support class for Introspector's
* internal use.
* <p>
* Mostly this is used as a placeholder for the descriptors.
大概不使用内部类的原因,是因为GenericBeanInfo基本上为Introspector所使用但又保留了给java.beans其他类使用的可能?这块的组织形式个人感觉比较别扭。
【最佳实践】
模型向视图对象vo转换时,vo属性设置为传给前端的类型,保持set、get方法类型一致,调用BeanUtils.copyProperties(dest, orig);通过org.apache.commons.beanutils.Converter转换器进行转换,而不要设置不同类型的get、set方法。
附:自定义类型转换器,注意这里Converter()的类型起名依据是转换后的类型,里面处理的是不同类型转换为转换后的类型的情况。
ConvertUtils.register(new XXXConverter(), java.lang.XXX.class);
BeanUtils.copyProperties(dest, orig);
Converter例子:
class DateConverter implements Converter {
@Override
public Object convert(Class type, Object value) {
if (value == null) {
return null;
}
if (value instanceof Date) {
return value;
}
if (value instanceof Long) {
Long longValue = (Long) value;
return new Date(longValue.longValue());
}
try {
return DateUtils.parseDate(value.toString(), new String[] { "yyyy-MM-dd HH:mm:ss.SSS",
"yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM-dd" });
} catch (Exception e) {
throw new ConversionException(e);
}
}
}
就改了get,却不让我set?——Java内省机制的神奇行为举止一例的更多相关文章
- java- 综合实例-增删查改查,删除多项,分页,令牌机制
重点内容:分页.令牌机制(重定向下防止重复提交).使用c3p0连接数据库(以及数据库连接类) 项目结构: 类: 项目展示: 数据库: /* SQLyog Ultimate v12.09 (64 bit ...
- Java编程的逻辑 (62) - 神奇的序列化
本系列文章经补充和完善,已修订整理成书<Java编程的逻辑>,由机械工业出版社华章分社出版,于2018年1月上市热销,读者好评如潮!各大网店和书店有售,欢迎购买,京东自营链接:http:/ ...
- Java-马士兵设计模式学习笔记-观察者模式-读取properties文件改成单例模式
一.概述 1.目标:读取properties文件改成单例模式 二.代码 1.Test.java class WakenUpEvent{ private long time; private Strin ...
- Android——另外一种增删查改的方式(ContentProvider常用)
以下介绍另外一种增删查改的方式 package com.njupt.sqllist; import java.util.ArrayList; import java.util.List; import ...
- APK改之理 手游修改改编安卓程序工具安装使用教程
APK改之理 手游修改改编安卓程序工具安装使用教程 --APK破解付费程序 apk改之理是pc平台上一款非常好用的apk反编译工具,他将反编译以及签名等功能集中在一起,并且拥有非常人性化的操作界面,如 ...
- Java笔试题:给定一个ReadOnlyClass的对象roc,能否把这个对象的age值改成30?
在Java笔试面试中,经常会遇到代码题,今天我们就来看一则Java代码笔试题. 有如下代码: Class ReadOnlyClass { private Integer age=20; public ...
- java1.8 版本改成 java1.7版本
以前先安装的java1.7 大部分程序应该都是只支持1.7 不支持1.8 但是因为要跑一个别人的项目 要求是java1.8 所以想在电脑上同时装1.7和1.8 到官网上下载1.8 安装 安装完成后 并 ...
- 【mybatis】mybatis动态order by 的问题, 注意 只需要把#{} 改成 ${} 即可
先说解决方案: 注意 只需要把#{} 改成 ${} 即可 再看 使用过程: Mapper.java List<IntegralGoods> findInUid(@Param(" ...
- Java版本:识别Json字符串并分隔成Map集合
前言: 最近又看了点Java的知识,于是想着把CYQ.Data V5迁移到Java版本. 过程发现坑很多,理论上看大部分很相似,实践上代码写起来发现大部分都要重新思考方案. 遇到的C#转Java的一些 ...
随机推荐
- C#基础知识总结(二)--泛型
什么是泛型 我们在编写程序时,经常遇到两个模块的功能非常相似,只是一个是处理int数据,另一个是处理string数据,或者其他自定义的数据类型,但我们没有办法,只能分别写多个方法处理每个数据类型,因为 ...
- [原创] Matlab 指派问题模型代码
指派问题的基本内容 一般来说指派问题解决的是如何将任务分配到人,使得任务完成的效益最大化(成本型效益则求最小值,利润型效益则求最大值).上述问题一个 0 - 1 整数规划问题. 问题围绕着任务和人展开 ...
- idea 安装 lombok插件
一,前言 lombok是什么?lombak是一个工具,主要用来简化,减少代码的编写.使代码看起来更清晰,简洁. 而且lombok只是一个工具,不会打包到war中,不会增加任何消耗.只是在编译期中帮助我 ...
- 深入全面理解面向对象的 JavaScript
深入全面理解面向对象的 JavaScript (原著: 曾 滢, 软件工程师, IBM,2013 年 4 月 17 日) JavaScript 函数式脚本语言特性以及其看似随意的编写风格,导致长期以来 ...
- centos文件解压缩7z
1.7z 安装 yum install p7zip 压缩test文件夹生成test.7z 7za a -t7z -r test.7z test #a 代表添加文件/文件夹到压缩包 -t 是指定压缩类型 ...
- python的pywinrm模块远程连接windows执行dos命令
----A机器远程连接B---- 在A机器上安装模块: pip install pywinrm 在B机器上配置winrm服务的相关配置,使其支持远程控制: (winrm服务是windows 一种方便远 ...
- 对Servlet执行流程的初步认识
这里我们以Post方式请求Serclet为例 1.找到 中的URL地址 Form表单的Post请求HelloServlet(Action="HelloServlet")发起时, A ...
- Redis数据库之KEY的操作与事务管理
目的 了解并掌握各种数据类型的命令操作方式,以及各种数据类型值的操作方式.同时,主要培养对KEY的操作命令运用的能力.重点掌握对KEY信息的管理.事务常规管理和事务回滚操作. KEYS命令的练习,对K ...
- GStreamer基础教程09 - Appsrc及Appsink
摘要 在我们前面的文章中,我们的Pipline都是使用GStreamer自带的插件去产生/消费数据.在实际的情况中,我们的数据源可能没有相应的gstreamer插件,但我们又需要将数据发送到GStre ...
- 序列标注(HMM/CRF)
目录 简介 隐马尔可夫模型(HMM) 条件随机场(CRF) 马尔可夫随机场 条件随机场 条件随机场的特征函数 CRF与HMM的对比 维特比算法(Viterbi) 简介 序列标注(Sequence Ta ...