天天看點

類加載器與反射,動态代理

類的加載概述和加載時機

A:類的加載概述

當程式要使用某個類時,如果該類還未被加載到記憶體中,則系統會通過加載,連接配接,初始化三步來實作對這個類進行初始化。

加載

就是指将class檔案讀入記憶體,并為之建立一個Class對象。

任何類被使用時系統都會建立一個Class對象。

連接配接

驗證 : 是否有正确的内部結構,并和其他類協調一緻

準備 : 負責為類的靜态成員配置設定記憶體,并設定預設初始化值

解析: 把類中的符号引用轉換為直接引用

初始化

就是我們以前講過的初始化步驟

B:類的加載時機

建立類的執行個體

通路類的靜态變量,或者為靜态變量指派

調用類的靜态方法

使用反射方式來強制建立某個類或接口對應的java.lang.Class對象

初始化某個類的子類

直接使用java.exe指令來運作某個主類

類加載器的概述和分類

A:類加載器的概述

負責将.class檔案加載到内在中,并為之生成對應的Class對象。

B:類加載器的分類

Bootstrap ClassLoader 根類加載器

Extension ClassLoader 擴充類加載器

Sysetm ClassLoader 系統類加載器

C:類加載器的作用

Bootstrap ClassLoader 根類加載器

也被稱為引導類加載器,負責Java核心類的加載

比如System,String等。在JDK中JRE的lib目錄下rt.jar檔案中

Extension ClassLoader 擴充類加載器

負責JRE的擴充目錄中jar包的加載。

在JDK中JRE的lib目錄下ext目錄

Sysetm ClassLoader 系統類加載器

負責在JVM啟動時加載來自java指令的class檔案,以及classpath環境變量所指定的jar包和類路徑

反射概述以及擷取class檔案對象的三種方式

A:反射概述

JAVA反射機制是在運作狀态中,對于任意一個類,都能夠知道這個類的所有屬性和方法;對于任意一個對象,都能夠調用它的任意一個方法和屬性;這種動态擷取類的資訊以及動态調用對象的方法的功能稱為java語言的反射機制。要想解剖一個類,必須先要擷取到該類的位元組碼檔案對象。而解剖使用的就是Class類中的方法,是以先要擷取到每一個位元組碼檔案對應的Class類型的對象

B:擷取class檔案對象的三種方式

a:Object類的getClass()方法

b:靜态屬性class

c:Class類中靜态方法forName()

C:案例示範: 擷取class檔案對象的三種方式

反射: 就是在運作狀态中的一種動态調用方法或者屬性的一種機制.

- 就是擷取位元組碼檔案對象,然後剖析改類中存在哪些構造方法,哪些成員變量,哪些成員方法

- 類的成員

  • 成員變量 Field
  • 構造方法 Constructor
  • 成員方法 Method

    - 如何擷取一個類對應的位元組碼檔案對象:

  • a: 第一種通過Object類中的getClass方法
  • b: 通過靜态屬性(class屬性)
  • c: 通過Class類中的一個靜态方法:
  • public static Class forName(String className):
  • className: 這個表示的是一個類對應的全類名(就是需要加上包名)
  • 類加載器與反射,動态代理
  • 類加載器與反射,動态代理

通過反射擷取無參構造方法并使用

A:擷取所有構造方法

public Constructor<?>[] getConstructors() 擷取所有的構造方法不包含私有的

public Constructor<?>[] getDeclaredConstructors() 擷取所有的構造方法 包括私有的

B:擷取單個構造方法

public Constructor getConstructor(Class<?>… parameterTypes) 擷取單個的構造方法 不包含私有的

public Constructor getDeclaredConstructor(Class<?>… parameterTypes) 擷取單個的構造方法包含私有的

C:案例示範: 通過反射擷取無參構造方法并使用

類加載器與反射,動态代理

通過反射擷取帶參構造方法并使用

A:案例示範: 通過反射擷取帶參構造方法并使用

類加載器與反射,動态代理
類加載器與反射,動态代理

通過反射擷取私有構造方法并使用

A:案例示範: 通過反射擷取私有構造方法并使用

// 擷取位元組碼檔案對象

Class clazz = Class.forName(“com.click369.Student”) ;

Constructor con = clazz.getDeclaredConstructor(String.class , int.class) ;

// 值為 true 則訓示反射的對象在使用時應該取消 Java 語言通路檢查。

con.setAccessible(true) ; 取消文法檢查不然會報錯 因為私有的外界不能直接通路

Object obj = con.newInstance(“張三” , 23) ;

System.out.println(obj);

類加載器與反射,動态代理
類加載器與反射,動态代理
類加載器與反射,動态代理

通過反射擷取成員變量并使用

A:擷取所有成員變量

public Field[] getFields() 擷取所有的成員變量包含從父類繼承過來的

public Field[] getDeclaredFields() 擷取所有的成員變量 包含私有的 也包含從父類繼承過來的成員變量

B:擷取單個成員變量

public Field getField(String name)

public Field getDeclaredField(String name)

C:案例示範: 通過反射擷取成員變量并使用

通過反射擷取無參無傳回值成員方法并使用

A:擷取所有成員方法

public Method[] getMethods() //擷取所有的公共的成員方法不包含私有的 包含從父類繼承過來的過來的公共方法

public Method[] getDeclaredMethods()//擷取自己的所有成員方法 包含私有的

B:擷取單個成員方法

//參數1: 方法名稱 參數2:方法行參的class 對象

public Method getMethod(String name,Class<?>… parameterTypes) //擷取單個的方法 不包含私有的

public Method getDeclaredMethod(String name,Class<?>… parameterTypes) 擷取單個方法包括私有的

C:案例示範: 通過反射擷取無參無傳回值成員方法并使用

類加載器與反射,動态代理
類加載器與反射,動态代理
類加載器與反射,動态代理

通過反射運作配置檔案内容

A:案例示範: 通過反射運作配置檔案内容

類加載器與反射,動态代理

過反射寫一個通用的設定某個對象的某個屬性為指定的值

A:案例示範

public void setProperty(Object obj, String propertyName, Object value){},

此方法可将obj對象中名為propertyName的屬性的值設定為value。

類加載器與反射,動态代理
類加載器與反射,動态代理

動态代理的概述和實作

A:動态代理概述

代理:本來應該自己做的事情,卻請了别人來做,被請的人就是代理對象。

舉例:春季回家買票讓人代買

動态代理:在程式運作過程中産生的這個對象

而程式運作過程中産生對象其實就是我們剛才反射講解的内容,是以,動态代理其實就是通過反射來生成一個代理

在Java中java.lang.reflect包下提供了一個Proxy類和一個InvocationHandler接口,通過使用這個類和接口就可以生成動态代理對象。JDK提供的代理隻能針對接口做代理。我們有更強大的代理cglib,Proxy類中的方法建立動态代理類對象。

public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)

最終會調用InvocationHandler的方法

InvocationHandler Object invoke(Object proxy,Method method,Object[] args)

B:案例示範: 動态代理的實作

public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)

loader: 類加載器

interfaces: 接口對應的一個Class數組

InvocationHandler: 這個其實就是要代理對象所做的事情的一個類的封裝

**注意:JDK給我們提供的動态代理,隻能對接口進行代理.

動态代理:

* 特點:位元組碼随用随建立,随用随加載

* 作用:不修改源碼的基礎上對方法增強

* 分類:

* 基于接口的動态代理

* 基于子類的動态代理

* 基于接口的動态代理:

* 涉及的類:Proxy

* 提供者:JDK官方

* 如何建立代理對象:

* 使用Proxy類中的newProxyInstance方法

* 建立代理對象的要求:

* 被代理類最少實作一個接口,如果沒有則不能使用

* newProxyInstance方法的參數:

* ClassLoader:類加載器

* 它是用于加載代理對象位元組碼的。和被代理對象使用相同的類加載器。固定寫法。

* Class[]:位元組碼數組

* 它是用于讓代理對象和被代理對象有相同方法。固定寫法。

* InvocationHandler:用于提供增強的代碼

* 它是讓我們寫如何代理。我們一般都是些一個該接口的實作類,通常情況下都是匿名内部類,但不是必須的。

* 此接口的實作類都是誰用誰寫。

* new InvocationHandler() {

/

* 作用:執行被代理對象的任何接口方法都會經過該方法

* 方法參數的含義

* @param proxy 代理對象的引用

* @param method 目前執行的方法

* @param args 目前執行方法所需的參數

* @return 和被代理對象方法有相同的傳回值

*/

@Override

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

}

}

類加載器與反射,動态代理
類加載器與反射,動态代理
類加載器與反射,動态代理
類加載器與反射,動态代理