Java基础之BeanInfo
Java的BeanInfo在工作中并不怎么用到,我也是在学习spring源码的时候,发现SpringBoot启动时候会设置一个属叫"spring.beaninfo.ignore",网上只能搜索到这个配置的意思是是否跳过java BeanInfo的搜索,没找到其他信息,但是BeanInfo又是什么呢?
JavaBean介绍
维基百科JavaBean的定义:JavaBeans是Java中一种特殊的类,可以将多个对象封装到一个对象(bean)中。特点是可序列化,提供无参构造器,提供getter方法和setter方法访问对象的属性。名称中的“Bean”是用于Java的可重用软件组件的惯用叫法。要成为JavaBean类,则必需遵循关于命名、构造器、方法的特定规范。有了这些规范,才能有可以使用、复用、替代和连接JavaBeans的工具。规范如下:
- 有一个public的无参数构造器。
- 属性可以通过get、set、is(可以替代get,用在布尔型属性上)方法或遵循特定命名规范的其他方法访问。
- 可序列化。
public class PersonBean implements java.io.Serializable {/**
* name 属性(注意大小寫)
*/
private String name = null;
private boolean deceased = false;
/** 无参构造器(没有参数) */
public PersonBean() {
}/**
* name 属性的Getter方法
*/
public String getName() {
return name;
}/**
* name 属性的Setter方法
* @param value
*/
public void setName(final String value) {
name = value;
}/**
* deceased 属性的Getter方法
* 布尔型属性的Getter方法的不同形式(这里使用了is而非get)
*/
public boolean isDeceased() {
return deceased;
}/**
* deceased 属性的Setter方法
* @param value
*/
public void setDeceased(final boolean value) {
deceased = value;
}
}
文章图片
JavaBean的自省 用一个简单的SpringMVC用户登录的场景来描述一下JavaBean的自省,用户登录时候,前端表单传递的参数通常是一个如下Json字符串:
{
"username":"xxx",
"password":"xxxx"
}
后端接受表单的地方,通常可以使用一个JavaBean用RequestBody的形式接收参数:
public void login(@RequestBody LoginRequest request){
// Do login
}
其中,LoginRequest类似于如下的格式:
public class LoginRequest {
public String getUsername() {
return username;
}public void setUsername(String username) {
this.username = username;
}public String getPassword() {
return password;
}public void setPassword(String password) {
this.password = password;
}private String username;
private String password;
}
那么前端的Json如何映射到后端LoginRequest中的对应属性之上呢?可以看到LoginRequest中的字段都是private类型,无法直接设置字段值(反射虽然可以设置,但是并不合适),只能通过Setter方法进行设置,但是程序怎么知道JavaBean有哪些Setter方法呢?此处就用到了JavaBean的内省机制。
文章图片
JavaBean内省工具Introspector Java bean的工具包中提供了java内省工具Introspector,该工具可以通过以下方法获取Java bean 的内省结果BeanInfo(后文详细介绍),获取BeanInfo的流程如下图所示
// 在Object类时候停止检索,可以选择在任意一个父类停止
BeanInfo beanInfo = Introspector.getBeanInfo(JavaBeanDemo.class,Object.class);
文章图片
JavaBean内省结果BeanInfo 通过java的内省工具Introspector的getBeanInfo方法,我们可以获取一个JavaBean的内省BeanInfo,获取到的BeanInfo包含以下属性:
- Bean的类相关信息
- Bean的事件信息
- Bean的属性信息
- Bean的方法信息
- 额外属性信息
- Component的图标
文章图片
内省结果BeanInfo的类型 BeanInfo只是一个内省结果的接口,Java中对该接口的实现有以下三种:
- ApplicationBeanInfo:Apple desktop相关的JavaBean内省结果
- ComponentBeanInfo:Java Awt组件的内省结果,如按钮等
- GenericBeanInfo:通用的内省结果,JEE开发中的内省结果都为该类型
文章图片
Spring的BeanUtils.copyProperties BeanUtils.copyProperties用户在两个对象之间进行属性的复制,底层基于JavaBean的内省机制,通过内省得到拷贝源对象和目的对象属性的读方法和写方法,然后调用对应的方法进行属性的复制。以下为BeanUtils.copyProperties的流程
文章图片
BeanUtils对JavaBean内省的一些机制进行优化,到这里,大家有没有发现Java内省的一些缺点呢?
BeanUtils并发问题优化 Java内省的结果会缓存在ThreadGroupContext中,并且通过synchonrized关键字对缓存加锁(下图中的红框部分),导致同一个线程组中的线程无法并行内省。
文章图片
Spring的BeanUtils在Java内省之上又添加了一层缓存,这层缓存使用ConcurrentHashMap实现,从而提高了内省的效率。
BeanUtils Setter属性识别优化 在Java默认的内省过程中,setter方法的返回值必须是null,如果不是null的话,无法识别为有效的JavaBean属性(下图中的红色部分),Spring 自定义了一个BeanInfo ExtendedBeanInfo解决了这个问题。
文章图片
spring.beaninfo.ignore 回到最初提到的spring.beaninfo.ignore,这个配置用来忽略所有自定义的BeanInfo类的搜索.
BeanUtils 性能测试
复制方法 | 1万次复制耗时 | 1百万次复制耗时 | 1亿次复制耗时 |
---|---|---|---|
ModelMapper复制 | 262mills | 3875mills | 283177mills |
BeanUtils复制 | 3mills | 369mills | 20347mills |
直接复制 | 约等于0mills | 5mills | 438mills |
public class BeanUtilsPerformanceTest {public static void main(String[] args){
// 预热虚拟机
loopBeanUtils(100000);
loopCopyByHand(100000);
// 复制1万次的情况
System.out.println("\nloop 10000 times:");
loopBeanUtils(10000);
loopCopyByHand(10000);
// 复制1百万次的情况
System.out.println("\nloop 1000000 times:");
loopBeanUtils(1000000);
loopCopyByHand(1000000);
// 复制1亿次的情况
System.out.println("\nloop 100000000 times:");
loopBeanUtils(100000000);
loopCopyByHand(100000000);
}private static void loopBeanUtils(int loopTimes){
TestBeanDemo source = new TestBeanDemo();
TestBeanDemo target = new TestBeanDemo();
long start = System.currentTimeMillis();
for (int i=0;
i
【Java基础之BeanInfo】我是御狐神,欢迎大家关注我的微信公众号
文章图片
版权所有,禁止转载!
推荐阅读
- JAVA(抽象类与接口的区别&重载与重写&内存泄漏)
- PMSJ寻平面设计师之现代(Hyundai)
- 太平之莲
- 闲杂“细雨”
- 七年之痒之后
- 深入理解Go之generate
- 由浅入深理解AOP
- 期刊|期刊 | 国内核心期刊之(北大核心)
- 生活随笔|好天气下的意外之喜
- 感恩之旅第75天