Springboot工具類ReflectionUtils使用教程
前言
ReflectionUtils應(yīng)該是Springboot內(nèi)置工具類梳理的最后一篇了,可能很多人都沒有聽說過這個工具類,這個類封裝的是一些與java反射相關(guān)的靜態(tài)工具方法??赡芎芏嗳艘仓婪瓷?,卻不怎么經(jīng)常使用反射。其實反射是一個很有用的技術(shù)點,我認(rèn)為是可以和AOP比肩的,甚至有過之而不及。大家都知道AOP是面向切面編程,可以在定義的切面前、后執(zhí)行一些操作,但是反射更厲害,它可以在程序運行時,對已裝載的任意類的屬性和方法進行操作,這就是java的反射機制。
ReflectionUtils
org.springframework.util.ReflectionUtils中包含的靜態(tài)方法其實有很多,主要分為兩類:對類中屬性的操作和對類中方法的操作。
對屬性的操作
獲取屬性字段
Field findField(Class clazz,Stringname),在類中查找指定屬性。
@Test public void test1(){ //查找屬性字段realName Field realName = ReflectionUtils.findField(Employee.class, "realName"); Assert.notNull(realName, "獲取員工類的姓名屬性失敗"); }
Field findField(Class clazz,Stringname, Classtype),更精確的在類中查找指定屬性,可以在指定屬性的類型。
@Test public void test2(){ //查找屬性字段realName,類型是String Field realName = ReflectionUtils.findField(Employee.class, "realName",String.class); Assert.notNull(realName, "獲取員工類的姓名屬性失敗"); }
設(shè)置屬性字段的值
ObjectgetField(Field field,Objecttarget),獲取 target 對象的 field 屬性值。
@Test public void test3() { //聲名一個對象,姓名是zhangsan Employee zhangsan = new Employee("zhangsan"); //獲取Employee類中的realName屬性字段 Field field = ReflectionUtils.findField(Employee.class, "realName"); //取消realName屬性的private權(quán)限控制 ReflectionUtils.makeAccessible(field); //獲取員工對象的姓名字段的值 Object value = ReflectionUtils.getField(field, zhangsan); Assert.isTrue(value.equals("zhangsan"),"員工zhangsan的姓名字段取值失敗" ); }
voidsetField(Field field,Objecttarget,Objectvalue),可以設(shè)置 target 對象的 field 屬性值,值為 value。
@Test public void test4() { Employee zhangsan = new Employee("zhangsan"); //獲取Employee類中的realName屬性字段 Field field = ReflectionUtils.findField(Employee.class, "realName"); //取消realName屬性的private權(quán)限控制 ReflectionUtils.makeAccessible(field); //把員工對象zhangsan的姓名字段值設(shè)置為zhangsan_v2 ReflectionUtils.setField(field, zhangsan, "zhangsan_v2"); Object value = ReflectionUtils.getField(field, zhangsan); Assert.isTrue(value.equals("zhangsan_v2"),"員工zhangsan的姓名字段取值失敗" ); }
voidshallowCopyFieldState(Objectsrc,Objectdest),如果兩個對象是同一個類的實現(xiàn),且希望把一對象的值復(fù)制到另外一個對象上,可以使用這個方法,src是源對象,dest是目標(biāo)對象。
@Test public void test5() { Employee zhangsan = new Employee("zhangsan"); Employee tmp = new Employee(); //把對象zhangsan的值復(fù)制到對象tmp上,這里要注意,復(fù)制的對象類型要相同 ReflectionUtils.shallowCopyFieldState(zhangsan, tmp); Assert.isTrue(tmp.getRealName().equals("zhangsan"),"對象的屬性復(fù)制失敗了" ); }
voidmakeAccessible(Field field),取消java的權(quán)限控制檢查,方便private私有訪問權(quán)限的操作。
@Test public void test4() { Employee zhangsan = new Employee("zhangsan"); //取消realName屬性的private權(quán)限控制 ReflectionUtils.makeAccessible(field); }
voiddoWithFields(Class clazz, ReflectionUtils.FieldCallback fc),可以對類的每個屬性執(zhí)行 回調(diào)方法,簡單的理解就是可以定義一個回調(diào)方法,在對類的屬性操作完后,回調(diào)方法內(nèi)的邏輯就會被執(zhí)行。另外還有兩個方法,功能也很類似:void doWithFields(Class clazz, ReflectionUtils.FieldCallback fc,ReflectionUtils.FieldFilter ff),不僅有回調(diào)方法,還可以增加過濾的邏輯;voiddoWithLocalFields(Class clazz, ReflectionUtils.FieldCallback fc),只對本類的屬性可以執(zhí)行回調(diào)方法,不包括父類的。舉個例子,簡單的理解一下,實在理解不了就放棄吧,因為我也覺得這個確實有點雞肋。假如員的性別在程序中是以1和0進行區(qū)分,對外展示的時候要轉(zhuǎn)換為“男”和“女”:
public class SexFieldCallBack<T> implements ReflectionUtils.FieldCallback{ private Object obj; private Integer sexFlag=-1; public SexFieldCallBack(Object obj) { this.obj = obj; } @Override public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException { field.setAccessible(true); if (field.getName().equals("sexFlag")) { Object value = field.get(obj); this.sexFlag= ((Integer) value); } if(field.getName().equals("sex")){ if (1==this.sexFlag) { field.set(obj, "男"); } if (0==this.sexFlag) { field.set(obj, "女"); } } } }
@Test public void test6() throws IllegalAccessException, InstantiationException { Employee employee = Employee.class.newInstance(); employee.setRealName("zhangsan"); //性別標(biāo)志位,1:男,0:女 employee.setSexFlag(1); ReflectionUtils.doWithFields(Employee.class,new SexFieldCallBack(employee) ); Assert.isTrue("男".equals(employee.getSex()), "性別轉(zhuǎn)換失敗了"); }
對方法的操作
@Data public class Employee implements Serializable { private String realName; public void hello(String name) { System.out.println(name + ",你好!我是" + this.realName); } public void say(String name) { System.out.println(name + ",你好!我是" + this.realName); } public String hello(String name, Boolean isReturn) { String msg = name + ",你好!我是" + this.realName; if (isReturn) { System.out.println(msg); return msg; } return null; } }
獲取方法
Method findMethod(Classclazz,Stringname),在類中查找指定名字方法
@Test public void test7() throws IllegalAccessException, InstantiationException, InvocationTargetException { //查找類中的hello方法 //這里要注意如果類中有方法名相同的重載方法時,一要要用下面的方法,把參數(shù)的類型給帶上 //如果不是重載方法,用這個也沒問題 Method say = ReflectionUtils.findMethod(Employee.class, "say"); Employee employee = Employee.class.newInstance(); employee.setRealName("zhangsan"); say.invoke(employee, "lisi"); }
Method findMethod(Class clazz,Stringname, Class... paramTypes),有的時候同一個類可能會有多個方法名相同,形參數(shù)不同的重載方法,可以使用這個方法更精確的在類中找到指定方法;
@Test public void test8() throws IllegalAccessException, InstantiationException, InvocationTargetException { Method hello = ReflectionUtils.findMethod(Employee.class, "hello",String.class,Boolean.class); Employee employee = Employee.class.newInstance(); employee.setRealName("zhangsan"); //執(zhí)行employee對象的hello方法 Object msg = hello.invoke(employee, "lisi",true); System.out.println(msg); }
Method[] getAllDeclaredMethods(Class leafClass),獲得類中所有方法,包括繼承而來的。
@Test public void test9() { //獲取類中所有的方法,包括繼承而來的 Method[] methods = ReflectionUtils.getAllDeclaredMethods(Employee.class); for (Method o : methods) { System.out.println(o.getName()); } }
執(zhí)行方法
ObjectinvokeMethod(Method method,Objecttarget),執(zhí)行無參數(shù)的方法;
ObjectinvokeMethod(Method method,Objecttarget,Object... args),執(zhí)行有參數(shù)的方法
voidmakeAccessible(Method method),如果是私有方法,可以取消 Java 權(quán)限檢查,以便后續(xù)執(zhí)行該私有方法
@Test public void test10() throws IllegalAccessException, InstantiationException, InvocationTargetException { //獲取set方法 Method setRealName = ReflectionUtils.findMethod(Employee.class, "setRealName", String.class); //反射實例化一個對象 Employee employee = Employee.class.newInstance(); //放開權(quán)限檢查 ReflectionUtils.makeAccessible(setRealName); //執(zhí)行set方法 setRealName.invoke(employee, "zhangsan"); //獲取get方法 Method getRealName = ReflectionUtils.findMethod(Employee.class, "getRealName"); //執(zhí)行g(shù)et方法 Object result = getRealName.invoke(employee); Assert.isTrue(result.equals("zhangsan"), "getRealName方法執(zhí)行失敗"); }
到此這篇關(guān)于Springboot工具類ReflectionUtils使用教程的文章就介紹到這了,更多相關(guān)Springboot ReflectionUtils內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Springboot程序在使用Maven下載依賴時失效的解決方法
以前能成功創(chuàng)建SpringBoot項目并運行,但是現(xiàn)在再創(chuàng)建新項目時Maven下載依賴失敗,且maven依賴刷新按鍵一直沒反應(yīng),所以本文給大家介紹了Springboot程序在使用Maven下載依賴時失效的解決方法,需要的朋友可以參考下2024-05-05關(guān)于spring.factories失效原因分析及解決
這篇文章主要介紹了關(guān)于spring.factories失效原因分析及解決,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-07-07使用Java WebSocket獲取客戶端IP地址的示例代碼
在開發(fā)Web應(yīng)用程序時,我們通常需要獲取客戶端的 IP 地址用于日志記錄、身份驗證、限制訪問等操作,本文將介紹如何使用Java WebSocket API獲取客戶端IP地址,以及如何在常見的WebSocket框架中獲得客戶端 IP地址,需要的朋友可以參考下2023-11-11