java用beaninfo_JavaBeanInfo 和 Spring 之间的关系

Java Beans

在这一章章节中笔者将和各位一起探讨关于 Java Beans 相关的内容。本章主要围绕 java.beans 这个包路径下的代码进行一些说明。

在 Spring 中我们可以看到 BeanInfoFactory 该接口可以用来获取 Class 对应的 BeanInfo 对象,在 CachedIntrospectionResults 中也有相关的成员变量作为信息存储,其他地方还有笔者就不再这里都去搜索了,各位可以自行查阅。

BeanInfoFactory public interface BeanInfoFactory {

@Nullable

BeanInfo getBeanInfo(Class> beanClass) throws IntrospectionException;

}

CachedIntrospectionResults public final class CachedIntrospectionResults {

private final BeanInfo beanInfo;

}

对于 Spring 来说操作 Bean 本身的内容其实是操作各类属性及其提供的方法。从笔者的角度来看 Bean 这个对象我觉得可以分成这三种,第一种是关于 Bean 属性的,第二种是关于属性操作的方法,第三种是提供外部操作的方法。就比如说现在有一个 People 对象,存在多个属性,我们在对这个 Bean 对象定义的时候正常情况下我们会放入 private 修饰的属性名,然后在提供 get 和 set 方法,如果有需要我们可以在通过非属性操作相关的方法。本章就暂时是对前两者的一个讨论。

首先我们来定义一个基本的 Java Bean

public class Student {

private String name;

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

}

现在我们用了一个名字叫做 Student 的 Java 对象,我们来看这个对象的解释

在 Student 对象中具有属性 name

在 Student 对象中存在字段 name

我们通常情况下会有这两种对象的定义解释,那么这个定义解释在 Java 中是如何对其进行定义的呢。在 Java 中有一个接口叫做 java.beans.BeanInfo 这个接口是用来描述 Java Bean 的接口,下面我们来看这个接口中存在的方法

BeanInfo 方法信息

public interface BeanInfo {

BeanDescriptor getBeanDescriptor();

EventSetDescriptor[] getEventSetDescriptors();

int getDefaultEventIndex();

PropertyDescriptor[] getPropertyDescriptors();

int getDefaultPropertyIndex();

MethodDescriptor[] getMethodDescriptors();

BeanInfo[] getAdditionalBeanInfo();

}

getBeanDescriptor :返回 Bean 的描述信息

getEventSetDescriptors:返回 Bean 相关的事件信息

getDefaultEventIndex:返回 Bean 默认事件索引

getPropertyDescriptors:返回 Bean 属性描述

getDefaultPropertyIndex:返回 Bean 默认的属性索引

getMethodDescriptors:返回 Bean 方法描述

getAdditionalBeanInfo :返回其他的 Bean Info 信息

下面我们先来对接口中的返回值做一些介绍

BeanDescriptor 成员变量表

变量名称

变量类型

变量说明

beanClassRef

Reference extends Class>>

bean 的类

customizerClassRef

Reference extends Class>>

自定义的类

PropertyDescriptor 成员变量表

变量名称

变量类型

变量说明

propertyTypeRef

Reference extends Class>>

属性类型

readMethodRef

MethodRef

读方法

writeMethodRef

MethodRef

写方法

propertyEditorClassRef

Reference extends Class>>

属性编辑类型

bound

boolean

constrained

boolean

baseName

String

writeMethodName

String

写方法名称

readMethodName

String

读方法名称

MethodDescriptor 成员变量表

变量名称

变量类型

变量说明

methodRef

MethodRef

方法

paramNames

String[]

参数名称

params

List>>

参数信息

parameterDescriptors

ParameterDescriptor

参数描述

在了解了上述三个对象后我们来编写一个测试用例,该测试用例主要用来获取 BeanInfo 接口数据

BeanInfo 测试用例

@Test

void classTest() throws IntrospectionException {

Class clazz = Student.class;

BeanInfo beanInfo = Introspector.getBeanInfo(clazz);

System.out.println();

}

BeanInfo 信息

b2955528d624fd4c7e74a92f5ee6b438.png

我们现在对 BeanInfo 有了一定的了解,接下来我们要通过 BeanInfo 来创建一个对象,并给该对象进行数据赋值,下面我们来写代码

@NotNull

private T getObject(Class clazz, Map prop) throws Exception {

// 获取 BeanInfo 接口

BeanInfo beanInfo = Introspector.getBeanInfo(clazz);

// 获取 Bean Class

Class> beanClass = beanInfo.getBeanDescriptor().getBeanClass();

// 获取所有的构造函数

Constructor>[] declaredConstructors = beanClass.getDeclaredConstructors();

// 确认构造函数: 直接取无参构造

Constructor constructor = confirmConstructor(declaredConstructors);

// 通过构造函数获取对象

Object bean = constructor.newInstance();

// 为对象设置属性

// 提取属性描述

PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();

for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {

// 属性名称

String name = propertyDescriptor.getName();

if (prop.containsKey(name)) {

// 写函数

Method writeMethod = propertyDescriptor.getWriteMethod();

// 从属性表中获取属性名称对应的属性值

Object proValue = prop.get(name);

writeMethod.invoke(bean, proValue);

}

}

return (T) bean;

}

编写这段代码的主要逻辑如下

通过 Class 获取 BeanInfo 接口

通过 BeanInfo 获取 beanClass

通过 beanClass 提取构造函数列表,从构造函数列表中选择一个具体的构造函数(这里采用无参构造的方式)

获取属性描述对象进行属性设置

编写完成后我们来写测试用例

@Test

void beanInfoCreateBean() throws Exception {

Class clazz = Student.class;

// 设置属性表

Map prop = new HashMap<>(8);

prop.put("name", "student_name");

Student bean = getObject(clazz, prop);

assert bean.getName().equals("student_name");

}

这样我们就完成了数据赋值,在上述过程中我们对于 beanClass 的获取可以直接使用参数传递的 clazz 直接使用,可以不需要通过 BeanInfo 接口进行二次调度。

下面我们来谈一谈 Spring 和 BeanInfo 的一些关联。

相信各位在使用 Spring XML 模式的时候会编写下面这样的内容。

这里我们抛开 Spring 中 Bean 生命周期相关的一些接口、占位符解析等内容,我们就简单的来看这个 标签,这个标签定义了一个 class 属性 和子标签 property ,我们可以通过一些 XML 解析工具得到这两个对象,Spring 在这会将 class 属性通过 ClassLoader 转换成 Class 会将 property 转换成对象 PropertyValue ,然后通过反射将对象创建出来。那么这段说明和我们所编写的通过 BeanInfo 创建 Bean 有什么关系呢?我们可以思考下面几个问题

知道了 BeanClass 如何才能创建对象呢?

知道属性名称和属性值如何给对象赋值呢?

这两个问题的答案很简单就是通过 Java 反射机制来进行处理,那么具体怎么做呢?这个问题的答案其实就是我们前面所编写的那段创建对象的代码。回过头我们来看这两个问题

第一个问题的答案:创建对象其本质是寻找构造函数并调用

第二个问题的答案:通过找到写方法将数据写入

Spring 中无参构造函数的调用

ce48d65011319aab413f4cde66f43ad5.png

有参构造的推论过程

28483d4f287eb84c6d3afd0808dca6ae.png

在这里做出了两种构造函数的推论,当完成推论构造函数后就可以进行对象创建及属性赋值了。

属性赋值相关的代码就不在截图了各位可以自行查找。

当我们有了 getObject 这样一个方法后,我们再来看一些生命周期,Spring 当中的各类生命周期其实就是围绕者这段代码的前后来做各种补充操作,

比如 InitializingBean 这个接口的调用时在 Bean 创建完成后,那么我们可以在具体的位置上补充这样一段

修改后的 getObject

@NotNull

private T getObject(Class clazz, Map prop) throws Exception {

// 获取 BeanInfo 接口

BeanInfo beanInfo = Introspector.getBeanInfo(clazz);

// 获取 Bean Class

Class> beanClass = beanInfo.getBeanDescriptor().getBeanClass();

// 获取所有的构造函数

Constructor>[] declaredConstructors = beanClass.getDeclaredConstructors();

// 确认构造函数: 直接取无参构造

Constructor constructor = confirmConstructor(declaredConstructors);

// 通过构造函数获取对象

Object bean = constructor.newInstance();

// 为对象设置属性

// 提取属性描述

PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();

for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {

// 属性名称

String name = propertyDescriptor.getName();

if (prop.containsKey(name)) {

// 写函数

Method writeMethod = propertyDescriptor.getWriteMethod();

// 从属性表中获取属性名称对应的属性值

Object proValue = prop.get(name);

writeMethod.invoke(bean, proValue);

}

}

if (bean instanceof InitializingBean) {

((InitializingBean) bean).afterPropertiesSet();

}

return (T) bean;

}

其他的一些生命周期接口也是可以通过类似的处理方式进行补充,笔者就不在这里进行展开了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/432934.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

selenium ruby和java_Selenium 2之Ruby版——安装篇

自从知道了Selenium的存在后&#xff0c;就一直都想&#xff0c;若要学习自动化&#xff0c;就要学习像Selenium这种比较有潜力的。Selenium有针对各种语言(java, C#, Python, Ruby, Perl)的版本&#xff0c;在此选择Ruby为学习方向&#xff0c;一来可以借此学习下Ruby&#xf…

基于visual Studio2013解决面试题之0702输出数字

&#xfeff;&#xfeff;&#xfeff;题目解决代码及点评/*输入数字 n&#xff0c;按顺序输出从 1 最大的 n 位 10 进制数。比如输入 3&#xff0c;则输出 1、2、3一直到最大的 3 位数即 999。 */#include <iostream> using namespace std;//在不考虑大数的情况下&#…

冠榕智能灯光控制协议分析(controller-node)

1. 在Z-WAVE PC Controller软件选择已配对的智能开关。 从上图中可以看到&#xff0c;我们的智能开关的node id是11&#xff0c;即0x0B。 2. 向智能开关发送灯光的开闭数据。 CommandClasses选择COMMAND_CLASS_BASIC CommandName选择BASIC_SET Value为00时关闭灯光&#xff0…

java中手动装入新类到类装饰器_关于java:抽象装饰器类中的功能而不是装饰器...

我目前正在阅读《Head First Design Patterns》一书&#xff0c;在"Decorator"一章中有以下示例&#xff1a;在书中&#xff0c;conditionmentDecorator类被描述为一个abstract decorator。下面是代码示例&#xff1a;public abstract class CondimentDecorator exte…

跨浏览器开发工作小结

本篇小结是在2011年时候总结的&#xff0c;当时做一个产品的跨浏览器兼容工作&#xff0c;由于产品开发的时间比较早&#xff0c;最开始只能在IE下面(IE 8、IE 9还有点点问题)使用&#xff0c;做跨浏览器兼容工作的时候&#xff0c;主要是适配IE 6--IE 9、Safari、FireFox、Chr…

冠榕智能灯光控制协议分析(node-controller)

1. 在Z-WAVE PC Controller软件选择已配对的智能开关。 从上图中可以看到&#xff0c;我们的智能开关的node id是11&#xff0c;即0x0B。 2. 按下智能开关&#xff0c;用串口工具可以看到以下信息。 01 0D 00 04 00 0B 07 60 0D 01 01 00 03 FF 6B 01 0D 00 04 00 0B 07 60…

冠榕智能灯光控制协议分析(controller-node) 2

z-wave第一篇&#xff0c;我们用COMMAND_CLASS_BASIC - BASIC_SET控制智能开关。但是智能开关上有两个执行器&#xff0c;我们只能控制其中一路&#xff0c;那么我们如何控制另一路的开关的。在z-wave第二篇&#xff0c;我们分析了智能开关两个按键发送的消息&#xff0c;发现&…

基于visual Studio2013解决面试题之0902内存拷贝

&#xfeff;&#xfeff;&#xfeff;题目解决代码及点评/*用 C 语言实现函数 void * memmove(void *dest,const void *src,size_t n)memmove 函数的功能是拷贝 src 所指的内存内容前 n 个字节到 dest 所指的地址上。 简单循环拷贝即可&#xff0c;但是这道题&#xff0c;要深…

冠榕智能灯光控制协议分析(controller init)

上面几篇已经详细介绍了z-wave协议的分析方法&#xff0c;这一章&#xff0c;我们分析z-wave pc controller初始化时的通信信息。我们只将关键信息列出&#xff0c;然后直接将分析出来的串口数据列出。 1. 得到z-wave版本 01 03 00 15 E9 06 01 10 01 15 5A 2D 57 61 76 65…

jmeter找不到java_Windows下Jmeter安装出现Not able to find Java executable or version问题解决方案...

最近在做一个开放接口平台性能测试 , 指标是最少达到1000/s的并发 , 接口鉴权 百万级的表 在1s内完成..在众多压测工具中 ,,选择了Apache的jmeter ,于官网下载了最新版本http://jmeter.apache.org/download_jmeter.cgi (jmeter下载地址)由于jmeter运行是基于java的,所以需要…

ZDB5304烧写方法

1&#xff0e; 跳线和5304的位置如下图 2. 打开z-wave programmer软件&#xff0c;设置如下图&#xff0c;注意烧写接口为uart&#xff0c;烧写的时候会提示的。选yes是uart&#xff0c;选no是spi。 烧写过程中会提示按下reset或释放reset按键。照做即可。 烧完后&#xff0c…

基于Z-Wave无线技术的指纹锁系统设计

http://www.chinaaet.com/article/218940 摘 要&#xff1a; 结合新兴的低功耗的Z-Wave短距无线通信技术&#xff0c;设计一种应用于酒店的智能指纹锁无线管理与控制系统。该系统的门锁硬件电路包括主控制器S3C2440、指纹采集模块、电机驱动模块及ZM3102无线模块&#xff0c;…

Hibernate一对一关联------主键关联(亲测成功)

1、创建两个实体&#xff08;Company.java和Login.java&#xff09;代码如下&#xff1a; 1 package wck.stu.vo.onetoonein;2 3 public class Company {4 private String id "";5 6 private String companyName "";7 8 private Str…

INTEL和AMD两大巨头的前身

仙童半导体公司&#xff0c;曾经是世界上最大、最富创新精神和最令人振奋的半导体生产企业&#xff0c;为硅谷的成长奠定了坚实的基础。更重要的是&#xff0c;这家公司还为硅谷孕育了成千上万的技术人才和管理人才&#xff0c;它不愧是电子、电脑业界的“西点军校”&#xff0…

servlet加载资源两种方式-内外(初始化参数).properties文件

在servlet中加载资源很方便&#xff0c;通过servletContext&#xff0c;这个是web服务器加载完web项目返回的参数之一&#xff0c;还有servletConfig&#xff0c;得到web项目一些配置信息&#xff0c;request和response,等等&#xff0c;我们现在用的这个servletContext也叫做C…

java 登录编程_Java编程通过session访问需要登录的页面

使用Java访问一般网页&#xff0c;进行数据抓取等比较简单&#xff0c;直接用URL和URLConnection连接所需要的网站地址即可&#xff0c;然后对返回的html源码进行处理分析&#xff0c;获取感兴趣的内容。不过如果是需要登录后才能访问的网页就不能直接传入网站url进行连接了&am…

ZDB5202烧成控制器方法

1&#xff0e;跳线和ZDB5202的安装位置如下图 黄色开关设置为off状态&#xff0c;就是靠近班子里面的一方。 2&#xff0e;打开z-wave programmer软件&#xff0c;设置如下图&#xff0c;注意烧写接口为spi&#xff0c;烧写的时候会提示的。选yes是uart&#xff0c;选no是spi。…

controller配对与接触配对

1&#xff0e; 当点击添加按钮后 以上数据&#xff0c;都是z-wave主控制器与pc controller软件的交换。 2&#xff0e; 当连续点击从结点的配对按钮后。 3&#xff0e; 当点击remove按钮后 4&#xff0e; 当连续点击从结点接触配对按钮后

php可以调用windowsapi吗_2.如何调用WindowsApi

2.如何调用WindowsApi在上一篇章节中 很不专业的介绍了一下WindowsApi 如果你本身就知道 那你也压根不用看 如果你本身就不知道 就算我说的再多 估计你也觉得是多余 所以还是来点实际的首先 在C#中想要调用那些Api(当然不一定是Windows提供的Api) 你得添加一个引用&#xff1a;…

php获取跳转后url,php获取跳转后真实url的方法

php获取跳转后真实url的方法发布时间&#xff1a;2020-08-01 14:17:56来源&#xff1a;亿速云阅读&#xff1a;68作者&#xff1a;清晨这篇文章主要介绍php获取跳转后真实url的方法&#xff0c;文中介绍的非常详细&#xff0c;具有一定的参考价值&#xff0c;感兴趣的小伙伴们一…