作者:京東物流 王國泰
一、什么是內(nèi)省
講內(nèi)省,不得不說Java Bean,Bean在Java中是一種特殊的類,主要用于裝載數(shù)據(jù),數(shù)據(jù)會被存儲在類的私有屬性中,通常具有無參構(gòu)造函數(shù)、可序列化、以及通過getter和setter方法來訪問屬性。內(nèi)省是Java Beans規(guī)范的一部分,使用java.beans包中的類來實現(xiàn),最常用的類是Introspector。通過內(nèi)省,你可以獲取一個Java Bean的屬性描述符(PropertyDescriptor)和方法描述符(MethodDescriptor)
二、內(nèi)省常用API
1、相關(guān)類
2、Introspector
2.1 核心功能
用于獲取Bean的整體信息,包括屬性描述符、方法描述符和事件描述符等
2.2 核心方法
getBeanInfo
BeanInfo beanInfo = Introspector.getBeanInfo(Vehicle.class);
3、BeanInfo
3.1 核心功能
用于提供有關(guān)Bean的元數(shù)據(jù),通常用于描述Bean的屬性、事件和方法
3.2 核心方法
getPropertyDescriptors
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
getMethodDescriptors
MethodDescriptor[] methodDescriptors = beanInfo.getMethodDescriptors();
getEventSetDescriptors
EventSetDescriptor[] eventSetDescriptors = beanInfo.getEventSetDescriptors();
4、PropertyDescriptor
4.1 核心功能
用于描述Bean的屬性,提供了對屬性的詳細描述,包括屬性的名稱、類型、讀方法getter、寫方法setter等
4.2 核心方法
getName
PropertyDescriptor namePD = new PropertyDescriptor("name", Vehicle.class); String name = namePD.getName();
getReadMethod
PropertyDescriptor namePD = new PropertyDescriptor("name", Vehicle.class); Method getter = namePD.getReadMethod(); String methodName = getter.getName(); String vehicleName = (String) getter.invoke(new Vehicle());
getWriteMethod
PropertyDescriptor namePD = new PropertyDescriptor("name", Vehicle.class); Method setter = namePD.getWriteMethod(); String methodName = setter.getName(); setter.invoke(new Vehicle(), "JD0001");
5、MethodDescriptor
5.1 核心功能
用于描述一個方法的屬性,提供了對方法的詳細描述,包括方法的名稱、參數(shù)類型、返回類型等
5.2 核心方法
getName
MethodDescriptor methodDescriptor = new MethodDescriptor(Vehicle.class.getMethod("setName", String.class)); String name = methodDescriptor.getName();
getMethod
MethodDescriptor methodDescriptor = new MethodDescriptor(Vehicle.class.getMethod("setName", String.class)); Method method = methodDescriptor.getMethod(); method.invoke(new Vehicle(), "JD0001");
6、EventSetDescriptor
6.1 核心功能
用于描述一個Bean能夠觸發(fā)的一組事件,提供了有關(guān)事件監(jiān)聽器類型、添加和移除監(jiān)聽器的方法以及事件通知方法的信息
6.2 核心方法
不常用
三、內(nèi)省常見使用場景
1、依賴注入
Spring使用內(nèi)省來分析類的構(gòu)造函數(shù)、字段和方法,并自動注入依賴對象,可參考BeanWrapperImpl,部分源碼如下:
@Override public PropertyDescriptor[] getPropertyDescriptors() { return getCachedIntrospectionResults().getPropertyDescriptors(); }
2、對象拷貝
Spring BeanUtils使用內(nèi)省來復(fù)制對象的屬性,可參考BeanUtils,部分源碼如下:
public static PropertyDescriptor[] getPropertyDescriptors(Class??> clazz) throws BeansException { return CachedIntrospectionResults.forClass(clazz).getPropertyDescriptors(); }
3、開發(fā)工具和IDE
開發(fā)工具和集成開發(fā)環(huán)境(IDE,如IntelliJ IDEA)使用內(nèi)省來提供代碼補全、重構(gòu)、調(diào)試等功能
四、內(nèi)省優(yōu)缺點
1、優(yōu)點
靈活性和可擴展性:允許在運行時動態(tài)地獲取和操作對象的屬性和方法
簡化開發(fā)工作:支持框架和工具的開發(fā),能夠自動處理對象的屬性和方法
2、缺點
性能開銷:比直接調(diào)用方法或訪問字段要慢,而且不當使用可能會導(dǎo)致內(nèi)存泄漏或增加GC壓力
訪問安全:繞過Java的訪問控制機制,訪問私有字段和方法,可能會帶來安全隱患,特別是在處理敏感數(shù)據(jù)時
類型安全:通常是基于字符串名稱進行的(如方法名、屬性名),在編譯時無法檢查其正確性,容易導(dǎo)致運行時錯誤
可讀性和可維護性:代碼可讀性差,增加調(diào)試難度
五、內(nèi)省與反射的區(qū)別
1、用途
內(nèi)省主要用于Java Bean的屬性操作,適合于標準化的Bean操作
反射則是更通用的機制,可以操作類的所有成員,包括私有成員
2、實現(xiàn)
內(nèi)省是基于Java Beans規(guī)范的,使用java.beans包
反射是Java語言的核心特性,使用java.lang.reflect包
3、性能
內(nèi)省通常比反射快,主要原因是內(nèi)省使用了緩存機制,減少了權(quán)限檢查,并且在設(shè)計上針對特定場景進行了優(yōu)化
相關(guān)文獻
JavaBeans API Specification:https://docs.oracle.com/javase/8/docs/api/java/beans/package-summary.html
《Java編程思想》(Thinking in Java) - Bruce Eckel
《Java核心技術(shù) 卷 I》(Core Java Volume I) - Cay S. Horstmann, Gary Cornell
《Java反射機制詳解》(Java Reflection in Action) - Ira R. Forman, Nate Forman
審核編輯 黃宇
-
JAVA
+關(guān)注
關(guān)注
19文章
2966瀏覽量
104702
發(fā)布評論請先 登錄
相關(guān)推薦
評論