-
內省(Introspector)概念
內省Introspector 是Java提供的操作 JavaBean 的 API,用來訪問某個屬性的 getter/setter 方法。對於一個標准的 JavaBean 來說,它包括屬性、get 方法和 set 方法,這是一個約定俗成的規范。為此 sun 提供了 Introspector 工具包,來使開發者更好或者更靈活的操作 JavaBean。
例如:User類中有個name屬性,那我們可以通過getName/setName來獲取/設置name的值,內省就是通過Java提供的API訪問屬性的getName()/setName()方法。
-
內省與反射的區別
在計算機科學中,內省是指計算機程序在運行時(Run time)檢查對象(Object)類型的一種能力,通常也可以稱作運行時類型檢查。 不應該將內省和反射混淆。相對於內省,反射更進一步,是指計算機程序在運行時(Run time)可以訪問、檢測和修改它本身狀態或行為的一種能力。
-
內省常用類說明
Introspector
類提供了的 getBeanInfo()方法獲取BeanInfo對象,可以拿到一個 JavaBean 的所有信息BeanInfo
通過getPropertyDescriptors() 方法和 getMethodDescriptors()方法可以獲取到PropertyDescriptors、MethodDescriptors對象MethodDescriptor
類可以獲得方法的元信息,比如方法名,參數個數,參數字段類型等- getMethod()獲取方法的Method對象
- getParameters() 獲取方法的所有參數Parameter列表
- getParameterTypes()獲取方法的參數ParameterType列表
PropertyDescriptor
類的主要方法- getPropertyType(),獲得屬性的Class對象
- getReadMethod()/getWriteMethod(),獲得用於讀取/寫入屬性值的方法
- setReadMethod(Method readMethod)/setWriteMethod(Method writeMethod),設置用於讀取/寫入屬性值的方法
-
代碼演示
-
MethodDescriptor
詳解// 使用Introspector獲取BeanInfo對象 BeanInfo beanInfo = Introspector.getBeanInfo(User.class); // 使用BeanInfo對象獲取到MethodDescriptor列表 MethodDescriptor[] methodDescriptors = beanInfo.getMethodDescriptors(); for (MethodDescriptor methodDescriptor : methodDescriptors) { // 獲取方法Method對象 Method method = methodDescriptor.getMethod(); // 獲取方法名稱 String methodName = method.getName(); // 參數類型列表 List<String> parameterTypeNames = new ArrayList<>(); Class<?>[] parameterTypes = method.getParameterTypes(); if (parameterTypes!=null && parameterTypes.length>0){ Arrays.stream(parameterTypes).forEach(x-> { String name = x.getName(); parameterTypeNames.add(name); }); } // 獲取方法參數Parameter數組 Parameter[] parameters = method.getParameters(); // 參數名稱列表 List<String> parameterNames = new ArrayList<>(); if (parameters!=null && parameters.length>0){ parameterNames = Arrays.stream(parameters).map(Parameter::getName).collect(Collectors.toList()); } System.out.println("方法名稱:"+methodName +" 參數類型列表:"+parameterTypeNames+" 參數名稱列表:"+parameterNames);
-
PropertyDescriptors
詳解// 使用Introspector獲取BeanInfo對象 BeanInfo beanInfo = Introspector.getBeanInfo(User.class); // 使用BeanInfo對象獲取到PropertyDescriptor列表 PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors(); for (PropertyDescriptor propertyDescriptor :propertyDescriptors) { // 獲取屬性名稱 String name = propertyDescriptor.getName(); if ("class".equals(name)){ continue; } // 獲取setter方法 Method writeMethod = propertyDescriptor.getWriteMethod(); // 獲取getter方法 Method readMethod = propertyDescriptor.getReadMethod(); System.out.println("屬性名稱:"+name+ " 賦值方法:"+writeMethod.getName()+ " 獲取方法:"+readMethod.getName()); } // 利用反射創建對象 User user = User.class.newInstance(); // 創建PropertyDescriptor對象 PropertyDescriptor propertyDescriptor = new PropertyDescriptor("name",User.class); // 獲取寫入方法並執行 Method writeMethod = propertyDescriptor.getWriteMethod(); writeMethod.invoke(user,"Rangers"); // 獲取讀取方法並執行 Method readMethod = propertyDescriptor.getReadMethod(); Object readPropertyValue = readMethod.invoke(user); System.out.println("ReadMethod獲取到到屬性值:"+readPropertyValue); System.out.println("getter獲取到到屬性值:"+user.getName()); // 設置寫入方法並執行 Method writeMd = User.class.getDeclaredMethod("setOoo",String.class); propertyDescriptor.setWriteMethod(writeMd); Method writeMethodAgain = propertyDescriptor.getWriteMethod(); writeMethodAgain.invoke(user, "ooo"); System.out.println("設置寫入方法重新賦值:"+user.getName());
-