作者:京東物流 王國(guó)泰
一、什么是內(nèi)省
講內(nèi)省,不得不說(shuō)Java Bean,Bean在Java中是一種特殊的類,主要用于裝載數(shù)據(jù),數(shù)據(jù)會(huì)被存儲(chǔ)在類的私有屬性中,通常具有無(wú)參構(gòu)造函數(shù)、可序列化、以及通過(guò)getter和setter方法來(lái)訪問(wèn)屬性。內(nèi)省是Java Beans規(guī)范的一部分,使用java.beans包中的類來(lái)實(shí)現(xiàn),最常用的類是Introspector。通過(guò)內(nèi)省,你可以獲取一個(gè)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的屬性,提供了對(duì)屬性的詳細(xì)描述,包括屬性的名稱、類型、讀方法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 核心功能
用于描述一個(gè)方法的屬性,提供了對(duì)方法的詳細(xì)描述,包括方法的名稱、參數(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 核心功能
用于描述一個(gè)Bean能夠觸發(fā)的一組事件,提供了有關(guān)事件監(jiān)聽(tīng)器類型、添加和移除監(jiān)聽(tīng)器的方法以及事件通知方法的信息
6.2 核心方法
不常用
三、內(nèi)省常見(jiàn)使用場(chǎng)景
1、依賴注入
Spring使用內(nèi)省來(lái)分析類的構(gòu)造函數(shù)、字段和方法,并自動(dòng)注入依賴對(duì)象,可參考BeanWrapperImpl,部分源碼如下:
@Override public PropertyDescriptor[] getPropertyDescriptors() { return getCachedIntrospectionResults().getPropertyDescriptors(); }
2、對(duì)象拷貝
Spring BeanUtils使用內(nèi)省來(lái)復(fù)制對(duì)象的屬性,可參考BeanUtils,部分源碼如下:
public static PropertyDescriptor[] getPropertyDescriptors(Class??> clazz) throws BeansException { return CachedIntrospectionResults.forClass(clazz).getPropertyDescriptors(); }
3、開(kāi)發(fā)工具和IDE
開(kāi)發(fā)工具和集成開(kāi)發(fā)環(huán)境(IDE,如IntelliJ IDEA)使用內(nèi)省來(lái)提供代碼補(bǔ)全、重構(gòu)、調(diào)試等功能
四、內(nèi)省優(yōu)缺點(diǎn)
1、優(yōu)點(diǎn)
靈活性和可擴(kuò)展性:允許在運(yùn)行時(shí)動(dòng)態(tài)地獲取和操作對(duì)象的屬性和方法
簡(jiǎn)化開(kāi)發(fā)工作:支持框架和工具的開(kāi)發(fā),能夠自動(dòng)處理對(duì)象的屬性和方法
2、缺點(diǎn)
性能開(kāi)銷:比直接調(diào)用方法或訪問(wèn)字段要慢,而且不當(dāng)使用可能會(huì)導(dǎo)致內(nèi)存泄漏或增加GC壓力
訪問(wèn)安全:繞過(guò)Java的訪問(wèn)控制機(jī)制,訪問(wèn)私有字段和方法,可能會(huì)帶來(lái)安全隱患,特別是在處理敏感數(shù)據(jù)時(shí)
類型安全:通常是基于字符串名稱進(jìn)行的(如方法名、屬性名),在編譯時(shí)無(wú)法檢查其正確性,容易導(dǎo)致運(yùn)行時(shí)錯(cuò)誤
可讀性和可維護(hù)性:代碼可讀性差,增加調(diào)試難度
五、內(nèi)省與反射的區(qū)別
1、用途
內(nèi)省主要用于Java Bean的屬性操作,適合于標(biāo)準(zhǔn)化的Bean操作
反射則是更通用的機(jī)制,可以操作類的所有成員,包括私有成員
2、實(shí)現(xiàn)
內(nèi)省是基于Java Beans規(guī)范的,使用java.beans包
反射是Java語(yǔ)言的核心特性,使用java.lang.reflect包
3、性能
內(nèi)省通常比反射快,主要原因是內(nèi)省使用了緩存機(jī)制,減少了權(quán)限檢查,并且在設(shè)計(jì)上針對(duì)特定場(chǎng)景進(jìn)行了優(yōu)化
相關(guān)文獻(xià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反射機(jī)制詳解》(Java Reflection in Action) - Ira R. Forman, Nate Forman
審核編輯 黃宇
-
JAVA
+關(guān)注
關(guān)注
19文章
2974瀏覽量
105094
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論