ホームページ  >  に質問  >  本文

java - spring ioc中为什么使用classloader,而不是Class.forName

阿神阿神2743日前534

全員に返信(1)返信します

  • 怪我咯

    怪我咯2017-04-18 10:53:03

    Class.forNameとClassLoader.loadClassの違い

    クラスローディング

    Class.forNameClassLoader.loadClass の違いを明確にするために、まず、JVM でのクラスのロード手順を理解する必要があります。
    クラスのロードは次のように行うことができます。次のステップに分かれています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 加载类的 ClassLoader 和调用 Class.forName 所在的类的 ClassLoader 相同.

    ClassLoader.loadClass

    Class.forName 不同, 默认情况下 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");

    • ロード: 完全修飾名を通じてクラスのバイナリ ストリームを取得し、それを JVM にロードします

    • 検証: クラス ファイルのバイト ストリームに含まれる情報が仮想マシンの要件を満たしており、仮想マシンのセキュリティを危険にさらさないことを確認します

    • 準備: クラス変数にメモリ領域を割り当て、クラス変数の初期値を設定します🎜
    • 🎜分析🎜
    • 🎜初期化: ユーザー指定のコードに従ってフィールドとその他のリソースを初期化し、静的ブロックを実行します。🎜
    🎜名前のクラス🎜 🎜通過するとき:🎜 リーリー 🎜クラスを取得するとき、実際には Class.forName(className, true, currentLoader) を呼び出すのと同じです。このメソッドの 2 番目のパラメータは、クラスを初期化する必要があるかどうかを示します。 code> true であるため、Class.forName が Class オブジェクトを取得すると、クラスが自動的に初期化されます。
    そして、Class.forName は、クラスの ClassLoader と、Class.forName と呼ばれる ClassLoader も同じです🎜 🎜ClassLoader.loadClass🎜 🎜 Class.forName とは異なり、ClassLoader.loadClass はデフォルトではクラスを初期化しません。つまり、クラス読み込みの initialization ステップは行われません。実行されるため、クラス内の静的コード ブロックは実行されません。
    また、ClassLoader.loadClass を使用する場合は、別の ClassLoader を指定できます。例: 🎜。 リーリー 🎜一例🎜 リーリー リーリー 🎜上記のコードでは、Class.forName("com.test.MyObj") の呼び出しにより、MyObj の静的コード ブロックの実行がトリガーされ、ClassLoader.getSystemClassLoader().loadClass( "com.test.MyObj"); はそうではありません。🎜 🎜この方法で使用する利点は何ですか? 🎜 🎜私の個人的な推測は、初期化を高速化するために、Spring IoC はクラスローダーを使用することで、クラス内で初期化コードを実行する必要がなくなります。読み込み速度を高速化します。初期化作業は、このクラスを実際に使用するまで残ります。

    返事
    0
  • キャンセル返事