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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

java用beaninfo_JavaBeanInfo 和 Spring 之间的关系

發布時間:2023/12/10 java 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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 信息

我們現在對 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 中無參構造函數的調用

有參構造的推論過程

在這里做出了兩種構造函數的推論,當完成推論構造函數后就可以進行對象創建及屬性賦值了。

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

當我們有了 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;

}

其他的一些生命周期接口也是可以通過類似的處理方式進行補充,筆者就不在這里進行展開了。

總結

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

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。