溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java內省Introspector相關類有哪些

發布時間:2021-11-30 14:48:56 來源:億速云 閱讀:170 作者:iii 欄目:大數據

本篇內容主要講解“Java內省Introspector相關類有哪些”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“Java內省Introspector相關類有哪些”吧!

JavaBean是什么

JavaBean是一種特殊(其實說普通也可以,也不是十分特殊)的類,主要用于傳遞數據信息,這種類中的方法主要用于訪問私有的字段,且方法名符合某種命名規則(字段都是私有,每個字段具備SetterGetter方法,方法和字段命名滿足首字母小寫駝峰命名規則)。如果在兩個模塊之間傳遞信息,可以將信息封裝進JavaBean中,這種對象稱為值對象(Value Object)或者VO。這些信息儲存在類的私有變量中,通過Setter、Getter方法獲得。JavaBean的信息在Introspector里對應的概念是BeanInfo,它包含了JavaBean所有的Descriptor(描述符),主要有PropertyDescriptor,MethodDescriptorMethodDescriptor里面包含ParameterDescriptor)、BeanDescriptorEventSetDescriptor。 

屬性Field和屬性描述PropertiesDescriptor的區別

如果是嚴格的JavaBean(Field名稱不重復,并且Field具備SetterGetter方法),它的PropertyDescriptor會通過解析SetterGetter方法,合并解析結果,最終得到對應的PropertyDescriptor實例。所以PropertyDescriptor包含了屬性名稱和屬性的SetterGetter方法(如果存在的話)。 

內省Introspector和反射Reflection的區別

  • Reflection:反射就是運行時獲取一個類的所有信息,可以獲取到類的所有定義的信息(包括成員變量,成員方法,構造器等)可以操縱類的字段、方法、構造器等部分??梢韵胂鬄殓R面反射或者照鏡子,這樣的操作是帶有客觀色彩的,也就是反射獲取到的類信息是必定正確的。
  • Introspector:內省基于反射實現,主要用于操作     JavaBean,基于     JavaBean的規范進行     Bean信息描述符的解析,依據于類的     Setter和     Getter方法,可以獲取到類的描述符??梢韵胂鬄?quot;自我反省",這樣的操作帶有主觀的色彩,不一定是正確的(如果一個類中的屬性沒有     Setter和     Getter方法,無法使用     Introspector)。 

常用的Introspector相關類

主要介紹一下幾個核心類所提供的方法。 

Introspector

Introspector類似于BeanInfo的靜態工廠類,主要是提供靜態方法通過Class實例獲取到BeanInfo,得到BeanInfo之后,就能夠獲取到其他描述符。主要方法:

  • public static BeanInfo getBeanInfo(Class<?> beanClass):通過     Class實例獲取到     BeanInfo實例。 

BeanInfo

BeanInfo是一個接口,具體實現是GenericBeanInfo,通過這個接口可以獲取一個類的各種類型的描述符。主要方法:

  • BeanDescriptor getBeanDescriptor():獲取     JavaBean描述符。
  • EventSetDescriptor[] getEventSetDescriptors():獲取     JavaBean的所有的     EventSetDescriptor。
  • PropertyDescriptor[] getPropertyDescriptors():獲取     JavaBean的所有的     PropertyDescriptor。
  • MethodDescriptor[] getMethodDescriptors():獲取     JavaBean的所有的     MethodDescriptor。

這里要注意一點,通過BeanInfo#getPropertyDescriptors()獲取到的PropertyDescriptor數組中,除了Bean屬性的之外,「還會帶有一個屬性名為classPropertyDescriptor實例」,它的來源是ClassgetClass方法,如果不需要這個屬性那么最好判斷后過濾,這一點需要緊記,否則容易出現問題。 

PropertyDescriptor

PropertyDescriptor類表示JavaBean類通過存儲器(SetterGetter)導出一個屬性,它應該是內省體系中最常見的類。主要方法:

  • synchronized Class<?> getPropertyType():獲得屬性的     Class對象。
  • synchronized Method getReadMethod():獲得用于讀取屬性值(     Getter)的方法;
  • synchronized Method getWriteMethod():獲得用于寫入屬性值(     Setter)的方法。
  • int hashCode():獲取對象的哈希值。
  • synchronized void setReadMethod(Method readMethod):設置用于讀取屬性值(     Getter)的方法。
  • synchronized void setWriteMethod(Method writeMethod):設置用于寫入屬性值(     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;
        }
    }
}
 

輸出結果:

age
setAge
getAge
=======================
id
setId
getId
=======================
name
setName
getName
=======================
   

不正當使用Introspector會導致內存溢出

如果框架或者程序用到了JavaBeans Introspector,那么就相當于「啟用了一個系統級別的緩存」,這個緩存會存放一些曾加載并分析過的Javabean的引用,當Web服務器關閉的時候,由于這個緩存中存放著這些Javabean的引用,所以垃圾回收器不能對Web容器中的JavaBean對象進行回收,導致內存越來越大。還有一點值得注意,清除Introspector緩存的唯一方式是刷新整個緩存緩沖區,這是因為JDK沒法判斷哪些是屬于當前的應用的引用,所以刷新整個Introspector緩存緩沖區會導致把服務器的所有應用的Introspector緩存都刪掉。Spring中提供的org.springframework.web.util.IntrospectorCleanupListener就是為了解決這個問題,它會在Web服務器停止的時候,清理一下這個Introspector緩存,使那些Javabean能被垃圾回收器正確回收。

也就是說JDKIntrospector緩存管理是有一定缺陷的。但是如果使用在Spring體系則不會出現這種問題,因為SpringIntrospector緩存的管理移交到Spring自身而不是JDK(或者在Web容器銷毀后完全不管),在加載并分析完所有類之后,會針對類加載器對Introspector緩存進行清理,避免內存泄漏的問題,詳情可以看CachedIntrospectionResultsSpringBoot刷新上下文的方法AbstractApplicationContext#refresh()finally代碼塊中存在清理緩存的方法AbstractApplicationContext#resetCommonCaches();。但是有很多程序和框架在使用了JavaBeans Introspector之后,都沒有進行清理工作,比如Quartz、Struts等,這類操作會成為內存泄漏的隱患。 

到此,相信大家對“Java內省Introspector相關類有哪些”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女