日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > java >内容正文

java

java用beaninfo_JavaBeanInfo 和 Spring 之间的关系

發(fā)布時(shí)間:2023/12/10 java 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java用beaninfo_JavaBeanInfo 和 Spring 之间的关系 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Java Beans

在這一章章節(jié)中筆者將和各位一起探討關(guān)于 Java Beans 相關(guān)的內(nèi)容。本章主要圍繞 java.beans 這個(gè)包路徑下的代碼進(jìn)行一些說(shuō)明。

在 Spring 中我們可以看到 BeanInfoFactory 該接口可以用來(lái)獲取 Class 對(duì)應(yīng)的 BeanInfo 對(duì)象,在 CachedIntrospectionResults 中也有相關(guān)的成員變量作為信息存儲(chǔ),其他地方還有筆者就不再這里都去搜索了,各位可以自行查閱。

BeanInfoFactory public interface BeanInfoFactory {

@Nullable

BeanInfo getBeanInfo(Class> beanClass) throws IntrospectionException;

}

CachedIntrospectionResults public final class CachedIntrospectionResults {

private final BeanInfo beanInfo;

}

對(duì)于 Spring 來(lái)說(shuō)操作 Bean 本身的內(nèi)容其實(shí)是操作各類屬性及其提供的方法。從筆者的角度來(lái)看 Bean 這個(gè)對(duì)象我覺(jué)得可以分成這三種,第一種是關(guān)于 Bean 屬性的,第二種是關(guān)于屬性操作的方法,第三種是提供外部操作的方法。就比如說(shuō)現(xiàn)在有一個(gè) People 對(duì)象,存在多個(gè)屬性,我們?cè)趯?duì)這個(gè) Bean 對(duì)象定義的時(shí)候正常情況下我們會(huì)放入 private 修飾的屬性名,然后在提供 get 和 set 方法,如果有需要我們可以在通過(guò)非屬性操作相關(guān)的方法。本章就暫時(shí)是對(duì)前兩者的一個(gè)討論。

首先我們來(lái)定義一個(gè)基本的 Java Bean

public class Student {

private String name;

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

}

現(xiàn)在我們用了一個(gè)名字叫做 Student 的 Java 對(duì)象,我們來(lái)看這個(gè)對(duì)象的解釋

在 Student 對(duì)象中具有屬性 name

在 Student 對(duì)象中存在字段 name

我們通常情況下會(huì)有這兩種對(duì)象的定義解釋,那么這個(gè)定義解釋在 Java 中是如何對(duì)其進(jìn)行定義的呢。在 Java 中有一個(gè)接口叫做 java.beans.BeanInfo 這個(gè)接口是用來(lái)描述 Java Bean 的接口,下面我們來(lái)看這個(gè)接口中存在的方法

BeanInfo 方法信息

public interface BeanInfo {

BeanDescriptor getBeanDescriptor();

EventSetDescriptor[] getEventSetDescriptors();

int getDefaultEventIndex();

PropertyDescriptor[] getPropertyDescriptors();

int getDefaultPropertyIndex();

MethodDescriptor[] getMethodDescriptors();

BeanInfo[] getAdditionalBeanInfo();

}

getBeanDescriptor :返回 Bean 的描述信息

getEventSetDescriptors:返回 Bean 相關(guān)的事件信息

getDefaultEventIndex:返回 Bean 默認(rèn)事件索引

getPropertyDescriptors:返回 Bean 屬性描述

getDefaultPropertyIndex:返回 Bean 默認(rèn)的屬性索引

getMethodDescriptors:返回 Bean 方法描述

getAdditionalBeanInfo :返回其他的 Bean Info 信息

下面我們先來(lái)對(duì)接口中的返回值做一些介紹

BeanDescriptor 成員變量表

變量名稱

變量類型

變量說(shuō)明

beanClassRef

Reference extends Class>>

bean 的類

customizerClassRef

Reference extends Class>>

自定義的類

PropertyDescriptor 成員變量表

變量名稱

變量類型

變量說(shuō)明

propertyTypeRef

Reference extends Class>>

屬性類型

readMethodRef

MethodRef

讀方法

writeMethodRef

MethodRef

寫(xiě)方法

propertyEditorClassRef

Reference extends Class>>

屬性編輯類型

bound

boolean

constrained

boolean

baseName

String

writeMethodName

String

寫(xiě)方法名稱

readMethodName

String

讀方法名稱

MethodDescriptor 成員變量表

變量名稱

變量類型

變量說(shuō)明

methodRef

MethodRef

方法

paramNames

String[]

參數(shù)名稱

params

List>>

參數(shù)信息

parameterDescriptors

ParameterDescriptor

參數(shù)描述

在了解了上述三個(gè)對(duì)象后我們來(lái)編寫(xiě)一個(gè)測(cè)試用例,該測(cè)試用例主要用來(lái)獲取 BeanInfo 接口數(shù)據(jù)

BeanInfo 測(cè)試用例

@Test

void classTest() throws IntrospectionException {

Class clazz = Student.class;

BeanInfo beanInfo = Introspector.getBeanInfo(clazz);

System.out.println();

}

BeanInfo 信息

我們現(xiàn)在對(duì) BeanInfo 有了一定的了解,接下來(lái)我們要通過(guò) BeanInfo 來(lái)創(chuàng)建一個(gè)對(duì)象,并給該對(duì)象進(jìn)行數(shù)據(jù)賦值,下面我們來(lái)寫(xiě)代碼

@NotNull

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

// 獲取 BeanInfo 接口

BeanInfo beanInfo = Introspector.getBeanInfo(clazz);

// 獲取 Bean Class

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

// 獲取所有的構(gòu)造函數(shù)

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

// 確認(rèn)構(gòu)造函數(shù): 直接取無(wú)參構(gòu)造

Constructor constructor = confirmConstructor(declaredConstructors);

// 通過(guò)構(gòu)造函數(shù)獲取對(duì)象

Object bean = constructor.newInstance();

// 為對(duì)象設(shè)置屬性

// 提取屬性描述

PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();

for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {

// 屬性名稱

String name = propertyDescriptor.getName();

if (prop.containsKey(name)) {

// 寫(xiě)函數(shù)

Method writeMethod = propertyDescriptor.getWriteMethod();

// 從屬性表中獲取屬性名稱對(duì)應(yīng)的屬性值

Object proValue = prop.get(name);

writeMethod.invoke(bean, proValue);

}

}

return (T) bean;

}

編寫(xiě)這段代碼的主要邏輯如下

通過(guò) Class 獲取 BeanInfo 接口

通過(guò) BeanInfo 獲取 beanClass

通過(guò) beanClass 提取構(gòu)造函數(shù)列表,從構(gòu)造函數(shù)列表中選擇一個(gè)具體的構(gòu)造函數(shù)(這里采用無(wú)參構(gòu)造的方式)

獲取屬性描述對(duì)象進(jìn)行屬性設(shè)置

編寫(xiě)完成后我們來(lái)寫(xiě)測(cè)試用例

@Test

void beanInfoCreateBean() throws Exception {

Class clazz = Student.class;

// 設(shè)置屬性表

Map prop = new HashMap<>(8);

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

Student bean = getObject(clazz, prop);

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

}

這樣我們就完成了數(shù)據(jù)賦值,在上述過(guò)程中我們對(duì)于 beanClass 的獲取可以直接使用參數(shù)傳遞的 clazz 直接使用,可以不需要通過(guò) BeanInfo 接口進(jìn)行二次調(diào)度。

下面我們來(lái)談一談 Spring 和 BeanInfo 的一些關(guān)聯(lián)。

相信各位在使用 Spring XML 模式的時(shí)候會(huì)編寫(xiě)下面這樣的內(nèi)容。

這里我們拋開(kāi) Spring 中 Bean 生命周期相關(guān)的一些接口、占位符解析等內(nèi)容,我們就簡(jiǎn)單的來(lái)看這個(gè) 標(biāo)簽,這個(gè)標(biāo)簽定義了一個(gè) class 屬性 和子標(biāo)簽 property ,我們可以通過(guò)一些 XML 解析工具得到這兩個(gè)對(duì)象,Spring 在這會(huì)將 class 屬性通過(guò) ClassLoader 轉(zhuǎn)換成 Class 會(huì)將 property 轉(zhuǎn)換成對(duì)象 PropertyValue ,然后通過(guò)反射將對(duì)象創(chuàng)建出來(lái)。那么這段說(shuō)明和我們所編寫(xiě)的通過(guò) BeanInfo 創(chuàng)建 Bean 有什么關(guān)系呢?我們可以思考下面幾個(gè)問(wèn)題

知道了 BeanClass 如何才能創(chuàng)建對(duì)象呢?

知道屬性名稱和屬性值如何給對(duì)象賦值呢?

這兩個(gè)問(wèn)題的答案很簡(jiǎn)單就是通過(guò) Java 反射機(jī)制來(lái)進(jìn)行處理,那么具體怎么做呢?這個(gè)問(wèn)題的答案其實(shí)就是我們前面所編寫(xiě)的那段創(chuàng)建對(duì)象的代碼。回過(guò)頭我們來(lái)看這兩個(gè)問(wèn)題

第一個(gè)問(wèn)題的答案:創(chuàng)建對(duì)象其本質(zhì)是尋找構(gòu)造函數(shù)并調(diào)用

第二個(gè)問(wèn)題的答案:通過(guò)找到寫(xiě)方法將數(shù)據(jù)寫(xiě)入

Spring 中無(wú)參構(gòu)造函數(shù)的調(diào)用

有參構(gòu)造的推論過(guò)程

在這里做出了兩種構(gòu)造函數(shù)的推論,當(dāng)完成推論構(gòu)造函數(shù)后就可以進(jìn)行對(duì)象創(chuàng)建及屬性賦值了。

屬性賦值相關(guān)的代碼就不在截圖了各位可以自行查找。

當(dāng)我們有了 getObject 這樣一個(gè)方法后,我們?cè)賮?lái)看一些生命周期,Spring 當(dāng)中的各類生命周期其實(shí)就是圍繞者這段代碼的前后來(lái)做各種補(bǔ)充操作,

比如 InitializingBean 這個(gè)接口的調(diào)用時(shí)在 Bean 創(chuàng)建完成后,那么我們可以在具體的位置上補(bǔ)充這樣一段

修改后的 getObject

@NotNull

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

// 獲取 BeanInfo 接口

BeanInfo beanInfo = Introspector.getBeanInfo(clazz);

// 獲取 Bean Class

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

// 獲取所有的構(gòu)造函數(shù)

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

// 確認(rèn)構(gòu)造函數(shù): 直接取無(wú)參構(gòu)造

Constructor constructor = confirmConstructor(declaredConstructors);

// 通過(guò)構(gòu)造函數(shù)獲取對(duì)象

Object bean = constructor.newInstance();

// 為對(duì)象設(shè)置屬性

// 提取屬性描述

PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();

for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {

// 屬性名稱

String name = propertyDescriptor.getName();

if (prop.containsKey(name)) {

// 寫(xiě)函數(shù)

Method writeMethod = propertyDescriptor.getWriteMethod();

// 從屬性表中獲取屬性名稱對(duì)應(yīng)的屬性值

Object proValue = prop.get(name);

writeMethod.invoke(bean, proValue);

}

}

if (bean instanceof InitializingBean) {

((InitializingBean) bean).afterPropertiesSet();

}

return (T) bean;

}

其他的一些生命周期接口也是可以通過(guò)類似的處理方式進(jìn)行補(bǔ)充,筆者就不在這里進(jìn)行展開(kāi)了。

總結(jié)

以上是生活随笔為你收集整理的java用beaninfo_JavaBeanInfo 和 Spring 之间的关系的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。