Spring進階——反射
阿新 • • 發佈:2020-09-15
引入
動態程式語言
變數並不是在計算機記憶體中被寫入的某個值,它們只是指向記憶體的“標籤”和“名稱”,所以動態程式語言的變數沒有一個固定的型別。Python
靜態程式語言
靜態程式語言的變數有固定的型別,它們指的是記憶體中的值。Java、C、C++
介紹
反射機制
動態獲取資訊以及動態呼叫物件方法的功能。
提供的功能
- 執行時,判斷任意一個物件所屬類
- 執行時,構造任意一個類的物件
- 執行時,判斷任意一個類所具有的成員方法和變數
- 執行時,呼叫任意一個物件的方法
- 生成動態代理
反射機制原理
RTTI 執行時型別資訊
執行期間,Java通過Class物件記錄每個物件RTTI,當編寫並編譯一個新類時,就會產生一個Class物件。
Class物件是在載入類時由JVM構造的,JVM為每個類管理一個獨一無二的Class物件。
動態的生成位元組碼(.class檔案),載入到JVM中執行。
使用的類
Class類
Class物件的由來是將class檔案讀入記憶體,併為之建立一個Class物件。 例項表示正在執行的Java應用程式中的類和介面。 獲取Class物件:
- Object.getClass();
- Class.getSuperClass();
- Class.forName();
- 對於包裝器型別:類名.TYPE屬性。
Field類
提供有關類和介面的屬性資訊,以及對其動態訪問許可權。
Constructor類
提供類的單個構造方法資訊,以及對其的訪問許可權。
Method類
提供類和介面單獨的某個方法的資訊。
功能使用
獲取物件的類
getClass()
//1.1 getClass() //獲取物件的類 String str = "hello world!"; cls = str.getClass(); System.out.println(cls.getName());
Class.forName()
- 類載入器載入方法
//1.2 Class.forName(); //根據具體包名來獲取類 //字串合法命名是類的名稱空間和類的名稱組成 cls = Class.forName("reflectprj.Student");
獲取類的父類
Class
物件且該物件有父類//1.3 getSuperclass(); //獲取類的父類 Class superCls = cls.getSuperclass();
獲取類的構造方法
- 獲取全部的構造方法
getDeclaredConstructors()
- 獲取特定的構造方法
getDeclaredConstructor(Class[] class)
- 建立構造方法建立例項
newInstance(引數)
//3.1 getDeclaredConstructors(); //獲取類的構造方法 Constructor[] constructors; constructors = cls.getDeclaredConstructors(); for(Constructor constructor:constructors) { System.out.println(constructor.toString()); } //3.1.2 //獲取類特定的構造方法 Class[] var = {int.class,String.class,String.class}; Constructor constructor = cls.getDeclaredConstructor(var); System.out.println(constructor.toString()); //4.1 newInstance(); //通過構造方法建立例項 Student stu = (Student)constructor.newInstance(1,"王小明","man"); System.out.println(stu.toString());
獲取類的方法
- 獲取全部的方法
getDeclaredMethods()
- 獲取特定的方法
getDeclaredMethod("方法名",Class[])
- 將物件與方法關聯,並呼叫方法。
invoke(物件名,引數)
- 如果方法為私有,則呼叫
method.setAccessible(true)
//3.2 getDeclaredMethod(); //獲取類的方法 Method [] ms = cls.getDeclaredMethods(); for(Method m:ms) { System.out.println(m.getName()); } //4.2 invoke(); //呼叫類的方法 Method m = cls.getDeclaredMethod("setSex", String.class); m.invoke(stu, "women"); System.out.println(stu.toString()); //5 setAccessible() //呼叫私有方法 m = cls.getDeclaredMethod("print", null); m.setAccessible(true); m.invoke(stu,null);
獲取類的屬性
- 獲取全部的屬性
getDeclaredFields()
- 獲取特定的屬性
getDeclaredField("fieldName")
- 將物件與屬性關聯,並設定屬性
set(物件名,屬性)
- 將物件與屬性關聯,獲取屬性
get(物件名)
- 如果屬性為私有,則呼叫
method.setAccessible(true)
//3.3 getDeclaredField() //獲取類的屬性 Field fs[] = cls.getDeclaredFields(); for(Field f:fs) { System.out.println(f.getName()); } //4.3 set(); //設定私有類屬性 Field f = cls.getDeclaredField("sex"); f.setAccessible(true); f.set(stu,"men"); System.out.println(f.get(stu).toString());
反射的應用
操作資料庫
動態建立SQL語句。
public void save(Object obj) {
String sql = "insert into ";
try {
Class cls = obj.getClass();
String clsName = cls.getSimpleName();
sql+=clsName;
sql+="(";
Field fs[] = cls.getDeclaredFields();
for(Field f:fs) {
sql+=f.getName()+",";
}
sql = sql.substring(0, sql.length()-1);
sql+=") values(";
Field fs1[] = cls.getDeclaredFields();
for(Field f:fs1) {
f.setAccessible(true);
sql+=f.get(obj)+",";
}
sql = sql.substring(0, sql.length()-1);
sql+=")";
}catch(Exception e) {
e.printStackTrace();
}
System.out.println(sql);
}
解析XML
解析XML動態生成物件。(Spring框架)
動態代理
框架使用
- Spring框架
- Hibernate框架
- Struts框架
缺點
反射對於效能有影響,反射基本上是一種解釋操作。 可以告訴JVM希望做什麼,讓其滿足要求。 這類操作慢於直接執行相同的操作。