本篇內(nèi)容主要講解“Java內(nèi)省Introspector相關(guān)類有哪些”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學(xué)習(xí)“Java內(nèi)省Introspector相關(guān)類有哪些”吧!
創(chuàng)新互聯(lián)專注于臨清企業(yè)網(wǎng)站建設(shè),響應(yīng)式網(wǎng)站設(shè)計,商城開發(fā)。臨清網(wǎng)站建設(shè)公司,為臨清等地區(qū)提供建站服務(wù)。全流程按需規(guī)劃網(wǎng)站,專業(yè)設(shè)計,全程項目跟蹤,創(chuàng)新互聯(lián)專業(yè)和態(tài)度為您提供的服務(wù)
JavaBean
是一種特殊(其實說普通也可以,也不是十分特殊)的類,主要用于傳遞數(shù)據(jù)信息,這種類中的方法主要用于訪問私有的字段,且方法名符合某種命名規(guī)則(字段都是私有,每個字段具備Setter
和Getter
方法,方法和字段命名滿足首字母小寫駝峰命名規(guī)則)。如果在兩個模塊之間傳遞信息,可以將信息封裝進(jìn)JavaBean
中,這種對象稱為值對象(Value Object
)或者VO
。這些信息儲存在類的私有變量中,通過Setter
、Getter
方法獲得。JavaBean
的信息在Introspector
里對應(yīng)的概念是BeanInfo
,它包含了JavaBean
所有的Descriptor
(描述符),主要有PropertyDescriptor
,MethodDescriptor
(MethodDescriptor
里面包含ParameterDescriptor
)、BeanDescriptor
和EventSetDescriptor
。
如果是嚴(yán)格的JavaBean
(Field
名稱不重復(fù),并且Field
具備Setter
和Getter
方法),它的PropertyDescriptor
會通過解析Setter
和Getter
方法,合并解析結(jié)果,最終得到對應(yīng)的PropertyDescriptor
實例。所以PropertyDescriptor
包含了屬性名稱和屬性的Setter
和Getter
方法(如果存在的話)。
Reflection
:反射就是運行時獲取一個類的所有信息,可以獲取到類的所有定義的信息(包括成員變量,成員方法,構(gòu)造器等)可以操縱類的字段、方法、構(gòu)造器等部分??梢韵胂鬄殓R面反射或者照鏡子,這樣的操作是帶有客觀色彩的,也就是反射獲取到的類信息是必定正確的。Introspector
:內(nèi)省基于反射實現(xiàn),主要用于操作
JavaBean
,基于
JavaBean
的規(guī)范進(jìn)行
Bean
信息描述符的解析,依據(jù)于類的
Setter
和
Getter
方法,可以獲取到類的描述符??梢韵胂鬄?自我反省",這樣的操作帶有主觀的色彩,不一定是正確的(如果一個類中的屬性沒有
Setter
和
Getter
方法,無法使用
Introspector
)。 主要介紹一下幾個核心類所提供的方法。
Introspector
類似于BeanInfo
的靜態(tài)工廠類,主要是提供靜態(tài)方法通過Class
實例獲取到BeanInfo
,得到BeanInfo
之后,就能夠獲取到其他描述符。主要方法:
public static BeanInfo getBeanInfo(Class> beanClass)
:通過
Class
實例獲取到
BeanInfo
實例。 BeanInfo
是一個接口,具體實現(xiàn)是GenericBeanInfo
,通過這個接口可以獲取一個類的各種類型的描述符。主要方法:
BeanDescriptor getBeanDescriptor()
:獲取
JavaBean
描述符。EventSetDescriptor[] getEventSetDescriptors()
:獲取
JavaBean
的所有的
EventSetDescriptor
。PropertyDescriptor[] getPropertyDescriptors()
:獲取
JavaBean
的所有的
PropertyDescriptor
。MethodDescriptor[] getMethodDescriptors()
:獲取
JavaBean
的所有的
MethodDescriptor
。這里要注意一點,通過BeanInfo#getPropertyDescriptors()
獲取到的PropertyDescriptor
數(shù)組中,除了Bean
屬性的之外,「還會帶有一個屬性名為class
的PropertyDescriptor
實例」,它的來源是Class
的getClass
方法,如果不需要這個屬性那么最好判斷后過濾,這一點需要緊記,否則容易出現(xiàn)問題。
PropertyDescriptor
類表示JavaBean
類通過存儲器(Setter
和Getter
)導(dǎo)出一個屬性,它應(yīng)該是內(nèi)省體系中最常見的類。主要方法:
synchronized Class> getPropertyType()
:獲得屬性的
Class
對象。synchronized Method getReadMethod()
:獲得用于讀取屬性值(
Getter
)的方法;synchronized Method getWriteMethod()
:獲得用于寫入屬性值(
Setter
)的方法。int hashCode()
:獲取對象的哈希值。synchronized void setReadMethod(Method readMethod)
:設(shè)置用于讀取屬性值(
Getter
)的方法。synchronized void setWriteMethod(Method writeMethod)
:設(shè)置用于寫入屬性值(
Setter
)的方法。舉個例子:
public class Main {
public static void main(String[] args) throws Exception {
BeanInfo beanInfo = Introspector.getBeanInfo(Person.class);
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
if (!"class".equals(propertyDescriptor.getName())) {
System.out.println(propertyDescriptor.getName());
System.out.println(propertyDescriptor.getWriteMethod().getName());
System.out.println(propertyDescriptor.getReadMethod().getName());
System.out.println("=======================");
}
}
}
public static class Person {
private Long id;
private String name;
private Integer age;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
}
輸出結(jié)果:
age
setAge
getAge
=======================
id
setId
getId
=======================
name
setName
getName
=======================
如果框架或者程序用到了JavaBeans Introspector
,那么就相當(dāng)于「啟用了一個系統(tǒng)級別的緩存」,這個緩存會存放一些曾加載并分析過的Javabean
的引用,當(dāng)Web
服務(wù)器關(guān)閉的時候,由于這個緩存中存放著這些Javabean
的引用,所以垃圾回收器不能對Web
容器中的JavaBean
對象進(jìn)行回收,導(dǎo)致內(nèi)存越來越大。還有一點值得注意,清除Introspector
緩存的唯一方式是刷新整個緩存緩沖區(qū),這是因為JDK
沒法判斷哪些是屬于當(dāng)前的應(yīng)用的引用,所以刷新整個Introspector
緩存緩沖區(qū)會導(dǎo)致把服務(wù)器的所有應(yīng)用的Introspector
緩存都刪掉。Spring
中提供的org.springframework.web.util.IntrospectorCleanupListener
就是為了解決這個問題,它會在Web
服務(wù)器停止的時候,清理一下這個Introspector
緩存,使那些Javabean
能被垃圾回收器正確回收。
也就是說JDK
的Introspector
緩存管理是有一定缺陷的。但是如果使用在Spring
體系則不會出現(xiàn)這種問題,因為Spring
把Introspector
緩存的管理移交到Spring
自身而不是JDK
(或者在Web
容器銷毀后完全不管),在加載并分析完所有類之后,會針對類加載器對Introspector
緩存進(jìn)行清理,避免內(nèi)存泄漏的問題,詳情可以看CachedIntrospectionResults
和SpringBoot
刷新上下文的方法AbstractApplicationContext#refresh()
中finally
代碼塊中存在清理緩存的方法AbstractApplicationContext#resetCommonCaches();
。但是有很多程序和框架在使用了JavaBeans Introspector
之后,都沒有進(jìn)行清理工作,比如Quartz
、Struts
等,這類操作會成為內(nèi)存泄漏的隱患。
到此,相信大家對“Java內(nèi)省Introspector相關(guān)類有哪些”有了更深的了解,不妨來實際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!