java - spring ioc中为什么使用classloader,而不是Class.forName
阿神
阿神 2017-04-18 10:51:03
0
1
500
  • spring ioc中为什么使用classloader,而不是Class.forName

  • 这样使用有什么好处?

  • 这两者有什么本质上的区别?

阿神
阿神

闭关修行中......

全部回覆 (1)
刘奇

Class.forName 和 ClassLoader.loadClass 的差別

類別載入

為了弄清楚Class.forNameClassLoader.loadClass的區別, 首先我們需要了解 JVM 中類加載的步驟.
類的加載可以分為如下幾步

  • 載入: 透過類別的全限定名取得到類別的二進位流, 然後載入到 JVM 中

  • 驗證: 確保Class 檔案的位元組流中包含的資訊符合虛擬機器的要求, 並且不會危害虛擬機器的安全

  • 準備: 為類別變數分配記憶體空間並設定類變初始值

  • 解析

  • 初始化: 根據使用者指定的程式碼初始化欄位和其他資源, 執行 static 區塊.

Class.forName

當我們通過:

Class.forName("com.test.MyObj")

來取得一個Class 時, 那麼其實相當於呼叫了Class.forName(className, true, currentLoader), 這個方法的第二個參數表示是否需要初始化類別. 我們設定為true, 因此Class.forName 取得到Class 物件時, 會自動對類別進行初始化的.Class.forName(className, true, currentLoader), 这个方法的第二个参数表示是否需要初始化类. 我们设置为true, 因此 Class.forName 获取到 Class 对象时, 会自动对类进行初始化的.
并且 Class.forName 加载类的 ClassLoader 和调用Class.forName並且Class.forName 載入類別的ClassLoader 和呼叫Class.forName所在的類別的ClassLoader相同.

ClassLoader.loadClass

Class.forName不同, 預設情況下ClassLoader.loadClass並不會初始化類別, 即類別載入的初始化步驟沒有執行, 因此類別中的靜態程式碼區塊不會執行.Class.forName不同, 默认情况下ClassLoader.loadClass并不会初始化类, 即类加载的初始化步骤没有执行, 因此类中的静态代码块不会执行.
并且使用ClassLoader.loadClass並且使用ClassLoader.loadClass時, 我們可以指定不同的ClassLoader. 例如:

ClassLoader.getSystemClassLoader().loadClass("com.test.MyObj");

一個例子

public class MyObj { static { System.out.println("MyObj class init."); } }
public class Test implements Cloneable, Serializable { public static void main(String[] args) throws Exception { Class.forName("com.test.MyObj"); // ClassLoader.getSystemClassLoader().loadClass("com.test.MyObj"); } }

那麼上面的程式碼中,Class.forName("com.test.MyObj")的调用会触发 MyObj 的静态代码块的执行, 而ClassLoader.getSystemClassLoader().loadClass("com.test.MyObj");並不會.

這樣使用有什麼好處?

我個人猜測, 應該和Spring IoC 的Lazy loading 有關, Spring IoC 為了加快初始化速度, 因此大量使用了延時加載技術. 而使用classloader 不需要執行類中的初始化代碼, 可以加快加載速度, 把類的初始化工作留到實際使用到這個類別的時候.

    最新下載
    更多>
    網站特效
    網站源碼
    網站素材
    前端模板
    關於我們 免責聲明 Sitemap
    PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!