有关Java中的BeanInfo介绍
作者:御狐神 发布时间:2023-08-05 00:13:42
1、JavaBean介绍
* JavaBean
的定义:JavaBeans
是Java中一种特殊的类,可以将多个对象封装到一个对象(bean
)中。特点是可序列化,提供无参构造器,提供getter方法和setter
方法访问对象的属性。名称中的“Bean
”是用于Java的可重用软件组件的惯用叫法。要成为JavaBean
类,则必需遵循关于命名、构造器、方法的特定规范。有了这些规范,才能有可以使用、复用、替代和连接JavaBeans
的工具。规范如下:
有一个public的无参数构造器。
属性可以通过
get
、set
、is
(可以替代get
,用在布尔型属性上)方法或遵循特定命名规范的其他方法访问。可序列化。
以下为一个合法的JavaBean的定义:
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;
}
}
2、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
的内省机制。
3、JavaBean内省工具Introspector
Java bean
的工具包中提供了java内省工具Introspector
,该工具可以通过以下方法获取Java bean
的内省结果BeanInfo
(后文详细介绍),获取BeanInfo
的流程如下图所示
// 在Object类时候停止检索,可以选择在任意一个父类停止
BeanInfo beanInfo = Introspector.getBeanInfo(JavaBeanDemo.class,Object.class);
4、JavaBean内省结果BeanInfo
通过java的内省工具Introspector
的getBeanInfo
方法,我们可以获取一个JavaBean
的内省BeanInfo
,获取到的BeanInfo包含以下属性:
Bean的类相关信息
Bean的事件信息
Bean的属性信息
Bean的方法信息
额外属性信息
Component的图标
5、内省结果BeanInfo的类型
BeanInfo只是一个内省结果的接口,Java中对该接口的实现有以下三种:
ApplicationBeanInfo:
Apple desktop
相关的JavaBean
内省结果ComponentBeanInfo:
Java Awt
组件的内省结果,如按钮等GenericBeanInfo:通用的内省结果,JEE开发中的内省结果都为该类型
此外,Spring
自定义了一个内省结果类型,叫ExtendedBeanInfo
,主要用于识别返回值不为空的Setter方法。
6、Spring的BeanUtils.copyProperties
BeanUtils.copyProperties
用户在两个对象之间进行属性的复制,底层基于JavaBean的内省机制,通过内省得到拷贝源对象和目的对象属性的读方法和写方法,然后调用对应的方法进行属性的复制。以下为BeanUtils.copyProperties
的流程
BeanUtils
对JavaBean
内省的一些机制进行优化,到这里,大家有没有发现Java内省的一些缺点呢?
7、BeanUtils并发问题优化
Java内省的结果会缓存在ThreadGroupContext
中,并且通过synchonrized
关键字对缓存加锁(下图中的红框部分),导致同一个线程组中的线程无法并行内省。
Spring
的BeanUtils
在Java内省之上又添加了一层缓存,这层缓存使用ConcurrentHashMap
实现,从而提高了内省的效率。
8、BeanUtils Setter属性识别优化
在Java默认的内省过程中,setter
方法的返回值必须是null
,如果不是null的话,无法识别为有效的JavaBean
属性(下图中的红色部分),Spring
自定义了一个BeanInfo ExtendedBeanInfo
解决了这个问题。
回到最初提到的spring.beaninfo.ignore
,这个配置用来忽略所有自定义的BeanInfo类的搜索.
9、BeanUtils 性能测试
可以看出:BeanUtils花费的时间约为直接复制的50倍以上。
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<loopTimes;i++){
BeanUtils.copyProperties(source,target);
}
System.out.println("BeanUtils cost times:"+String.valueOf(System.currentTimeMillis()-start));
}
private static void loopCopyByHand(int loopTimes){
TestBeanDemo source = new TestBeanDemo();
TestBeanDemo target = new TestBeanDemo();
long start = System.currentTimeMillis();
for (int i=0;i<loopTimes;i++){
target.setField1(source.getField1());
target.setField2(source.getField2());
target.setField3(source.getField3());
target.setField4(source.getField4());
target.setField5(source.getField5());
}
System.out.println("Copy field one by one times:"+String.valueOf(System.currentTimeMillis()-start));
}
@Data
private static class TestBeanDemo{
private String field1 = UUID.randomUUID().toString();
private String field2 = UUID.randomUUID().toString();
private String field3 = UUID.randomUUID().toString();
private String field4 = UUID.randomUUID().toString();
private String field5 = UUID.randomUUID().toString();
}
}
来源:https://www.cnblogs.com/yuhushen/p/15251010.html?utm_source=tuicool&utm_medium=referral


猜你喜欢
- 从SD卡中获取图片资源,或者拍一张新的图片。 先贴代码 获取图片: 注释:拍照获取的话,可以指定图片的保存地址,在此不说明。 CharSeq
- 引言热修复技术如今已经不是一个新颖的技术,很多公司都在用,而且像阿里、腾讯等互联网巨头都有自己的热修复框架,像阿里的AndFix采用的是ho
- 一、基本使用它们是 LockSupport 类中的方法// 暂停当前线程LockSupport.park(); // 恢复某个线程的运行Lo
- 一、概述Overview - LINQ to XML | Microsoft 官方文档LINQ to XMLLINQ to XML 是一种启
- 一、WebSocket简介WebSocket协议通过在客户端和服务端之间提供全双工通信来进行Web和服务器的交互功能。在WebSocket应
- 1 请求映射 在SpringBoot中使用@XxxMapping注解完成前端请求与后端方法的一个映射。以前的时候,通常使用url映射命名的
- 简单之美,springmvc,mybatis就是一个很好的简单集成方案,能够满足一般的项目需求。闲暇时间把项目配置文件共享出来,供大家参看:
- mac版本:点击Finder,在应用程序中找到android studio----->Contents文件夹----->bin文
- 在Android开发中,定时器一般有以下3种实现方法:一、采用Handler与线程的sleep(long)方法二、采用Handler的pos
- 本文实例为大家分享了JS Struts2多文件上传的具体代码,供大家参考,具体内容如下1、JSP页面: JS控制增加删除多个上传文件框,代码
- 前言:本文主要介绍内容有:一个串行调用的例子(App首页信息查询)CompletionService实现并行调用抽取通用的并行调用方法代码思
- 这篇文章主要介绍了Java使用Collections工具类对List集合进行排序,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一
- 因为在Action的execute方法声明时就抛出了Exception异常,所以我们无需再execute方法中捕捉异常,仅需在struts.
- 本文向大家分享的主要内容是Java面试中一个常见的知识点:volatile关键字。本文详细介绍了volatile关键字的方方面面,希望大家在
- 实现如下边框效果:虚线画效果,可以使用Android中的xml来做。下面话不多说,直接上代码:<RelativeLayout &nbs
- 1.简介学了几周的Java,闲来无事,写个乞丐版的扫雷,加强一下Java基础知识。2.编写过程编写这个游戏,一共经历了三个阶段,编写了三个版
- 本文实例为大家分享了Android自定义View实现标签流效果的具体代码,供大家参考,具体内容如下一、概述Android自定义View实现标
- 应用场景我们开发的控制台应用,在运行阶段很有可能被用户Ctrl+C终止或是被用户直接关闭。如果我们不希望用户通过Ctrl+C终止我们的程序,
- 现在的智能手机不敢说百分百的都是触摸屏,也应该是百分之九九以上为触摸屏了,触摸屏为我们操作无键盘、无鼠标的手机系统带来了很多的便利。当用户触
- 一、组件型注解:1、@Component 在类定义之前添加@Component注解,他会被spring容器识别,并转为bean。2、@Rep