Springboot工具類ReflectionUtils使用教程
前言
ReflectionUtils應(yīng)該是Springboot內(nèi)置工具類梳理的最后一篇了,可能很多人都沒(méi)有聽(tīng)說(shuō)過(guò)這個(gè)工具類,這個(gè)類封裝的是一些與java反射相關(guān)的靜態(tài)工具方法??赡芎芏嗳艘仓婪瓷?,卻不怎么經(jīng)常使用反射。其實(shí)反射是一個(gè)很有用的技術(shù)點(diǎn),我認(rèn)為是可以和AOP比肩的,甚至有過(guò)之而不及。大家都知道AOP是面向切面編程,可以在定義的切面前、后執(zhí)行一些操作,但是反射更厲害,它可以在程序運(yùn)行時(shí),對(duì)已裝載的任意類的屬性和方法進(jìn)行操作,這就是java的反射機(jī)制。
ReflectionUtils
org.springframework.util.ReflectionUtils中包含的靜態(tài)方法其實(shí)有很多,主要分為兩類:對(duì)類中屬性的操作和對(duì)類中方法的操作。
對(duì)屬性的操作
獲取屬性字段
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 對(duì)象的 field 屬性值。
@Test
public void test3() {
//聲名一個(gè)對(duì)象,姓名是zhangsan
Employee zhangsan = new Employee("zhangsan");
//獲取Employee類中的realName屬性字段
Field field = ReflectionUtils.findField(Employee.class, "realName");
//取消realName屬性的private權(quán)限控制
ReflectionUtils.makeAccessible(field);
//獲取員工對(duì)象的姓名字段的值
Object value = ReflectionUtils.getField(field, zhangsan);
Assert.isTrue(value.equals("zhangsan"),"員工zhangsan的姓名字段取值失敗" );
}voidsetField(Field field,Objecttarget,Objectvalue),可以設(shè)置 target 對(duì)象的 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);
//把員工對(duì)象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),如果兩個(gè)對(duì)象是同一個(gè)類的實(shí)現(xiàn),且希望把一對(duì)象的值復(fù)制到另外一個(gè)對(duì)象上,可以使用這個(gè)方法,src是源對(duì)象,dest是目標(biāo)對(duì)象。
@Test
public void test5() {
Employee zhangsan = new Employee("zhangsan");
Employee tmp = new Employee();
//把對(duì)象zhangsan的值復(fù)制到對(duì)象tmp上,這里要注意,復(fù)制的對(duì)象類型要相同
ReflectionUtils.shallowCopyFieldState(zhangsan, tmp);
Assert.isTrue(tmp.getRealName().equals("zhangsan"),"對(duì)象的屬性復(fù)制失敗了" );
}voidmakeAccessible(Field field),取消java的權(quán)限控制檢查,方便private私有訪問(wèn)權(quán)限的操作。
@Test
public void test4() {
Employee zhangsan = new Employee("zhangsan");
//取消realName屬性的private權(quán)限控制
ReflectionUtils.makeAccessible(field);
}voiddoWithFields(Class clazz, ReflectionUtils.FieldCallback fc),可以對(duì)類的每個(gè)屬性執(zhí)行 回調(diào)方法,簡(jiǎn)單的理解就是可以定義一個(gè)回調(diào)方法,在對(duì)類的屬性操作完后,回調(diào)方法內(nèi)的邏輯就會(huì)被執(zhí)行。另外還有兩個(gè)方法,功能也很類似:void doWithFields(Class clazz, ReflectionUtils.FieldCallback fc,ReflectionUtils.FieldFilter ff),不僅有回調(diào)方法,還可以增加過(guò)濾的邏輯;voiddoWithLocalFields(Class clazz, ReflectionUtils.FieldCallback fc),只對(duì)本類的屬性可以執(zhí)行回調(diào)方法,不包括父類的。舉個(gè)例子,簡(jiǎn)單的理解一下,實(shí)在理解不了就放棄吧,因?yàn)槲乙灿X(jué)得這個(gè)確實(shí)有點(diǎn)雞肋。假如員的性別在程序中是以1和0進(jìn)行區(qū)分,對(duì)外展示的時(shí)候要轉(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)換失敗了");
}對(duì)方法的操作
@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í),一要要用下面的方法,把參數(shù)的類型給帶上
//如果不是重載方法,用這個(gè)也沒(méi)問(wèn)題
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í)候同一個(gè)類可能會(huì)有多個(gè)方法名相同,形參數(shù)不同的重載方法,可以使用這個(gè)方法更精確的在類中找到指定方法;
@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對(duì)象的hello方法
Object msg = hello.invoke(employee, "lisi",true);
System.out.println(msg);
}Method[] getAllDeclaredMethods(Class leafClass),獲得類中所有方法,包括繼承而來(lái)的。
@Test
public void test9() {
//獲取類中所有的方法,包括繼承而來(lái)的
Method[] methods = ReflectionUtils.getAllDeclaredMethods(Employee.class);
for (Method o : methods) {
System.out.println(o.getName());
}
}執(zhí)行方法
ObjectinvokeMethod(Method method,Objecttarget),執(zhí)行無(wú)參數(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);
//反射實(shí)例化一個(gè)對(duì)象
Employee employee = Employee.class.newInstance();
//放開(kāi)權(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)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot項(xiàng)目中定時(shí)器的實(shí)現(xiàn)示例
在Spring?Boot項(xiàng)目中,你可以使用Spring框架提供的@Scheduled注解來(lái)編寫(xiě)定時(shí)任務(wù),本文就來(lái)介紹一下SpringBoot項(xiàng)目中定時(shí)器的實(shí)現(xiàn),感興趣的可以了解一下2023-11-11
Springboot程序在使用Maven下載依賴時(shí)失效的解決方法
以前能成功創(chuàng)建SpringBoot項(xiàng)目并運(yùn)行,但是現(xiàn)在再創(chuàng)建新項(xiàng)目時(shí)Maven下載依賴失敗,且maven依賴刷新按鍵一直沒(méi)反應(yīng),所以本文給大家介紹了Springboot程序在使用Maven下載依賴時(shí)失效的解決方法,需要的朋友可以參考下2024-05-05
關(guān)于spring.factories失效原因分析及解決
這篇文章主要介紹了關(guān)于spring.factories失效原因分析及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-07-07
使用Java WebSocket獲取客戶端IP地址的示例代碼
在開(kāi)發(fā)Web應(yīng)用程序時(shí),我們通常需要獲取客戶端的 IP 地址用于日志記錄、身份驗(yàn)證、限制訪問(wèn)等操作,本文將介紹如何使用Java WebSocket API獲取客戶端IP地址,以及如何在常見(jiàn)的WebSocket框架中獲得客戶端 IP地址,需要的朋友可以參考下2023-11-11
Maven項(xiàng)目繼承實(shí)現(xiàn)過(guò)程圖解
這篇文章主要介紹了Maven項(xiàng)目繼承實(shí)現(xiàn)過(guò)程圖解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-08-08

