1. 程式人生 > >執行緒上下文類載入器(Context ClassLoader)

執行緒上下文類載入器(Context ClassLoader)

1.執行緒上下文類載入器是從jdk1.2開始引入的,類Thread中的getContextClassLoader()與setContextClassLoader(ClassLoader c1),分別用來獲取和設定類載入器

如果沒有通過setContextClassLoader方法進行設定的話,執行緒將繼承其父執行緒的上下文載入器,java應用執行時的初始執行緒的上下文類載入器是系統類載入器(這裡是由Launcher類設定的)。線上程中執行的程式碼可以通過該類載入器來載入類和資源


2.執行緒上下文類載入器的重要性:

SPI(Service Provider Interface,服務提供者介面,指的是JDK提供標準介面,具體實現由廠商決定。例如sql)

父ClassLoader可以使用當前執行緒Thread.current.currentThread().getContextClassLoader()所指定的classLoader載入的類。這就改變了父ClassLoader不能使用子ClassLoader載入的類的情況,即改變了雙親委託模型。

執行緒上下文類載入器就是當前執行緒的CurrentClassloader。

在雙親委託模型下,類載入器是由下至上的,即下層的類載入器會委託上層進行載入。但是對於SPI來說,有些介面是JAVA核心庫提供的,而JAVA核心庫是由啟動類載入器來載入的,而這些介面的實現卻來自於不同的jar包(廠商提供),JAVA的啟動類載入器是不會載入其他來源的jar包,這樣傳統的雙親委託模型就無法滿足SPI的要求。而通過給當前執行緒設定上下文類載入器,就可以設定的上下文類載入器來實現對於介面實現類的載入。

3.執行緒上下文類載入器使用的一般模式:(獲取-使用-還原)

虛擬碼:

 ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
 try{
    Thread.currentThread().setContextClassLoader(targetTccl);
    excute();
 } finally {
    Thread.currentThread().setContextClassLoader(classLoader);
 }
4.當高層提供了統一的介面讓低層去實現,同時又要在高層載入(或者例項化)低層的類時,就必須要通過執行緒上下文類載入器來幫助高層的ClassLoader找到並載入該類