Java Web(2)クラスの初期化と初期化シーケンス

1.問題

最近、シングルトンパターンを作成するときに@Autiwiredアノテーションインジェクションの動作に遭遇しましたが、NULL調査の結果、これがクラスの初期化シーケンスに関連していることがわかりました。最初に私の質問を投げます:

//异步处理
public class AsyncManager {

    @Autowired
    ScheduledExecutorService scheduledExecutorService;

    /**
     * 操作延迟10毫秒
     */
    private final int OPERATE_DELAY_TIME = 10;

    /**
     * 静态AsyncManager,单例
     */
    private static AsyncManager manager = new AsyncManager();

    /**
     * 无参构造函数
     */
    private AsyncManager(){}

    /**
     * 单例模式(饿汉式)
     * @return AsyncManager
     */
    public static AsyncManager getManager() {
        return manager;
    }

    public void execute(TimerTask task) {
        scheduledExecutorService.schedule(task, OPERATE_DELAY_TIME, TimeUnit.MILLISECONDS);
    }

}
public SysUser login(String username, String password) {
    AsyncManager.getManager().execute(new TimerTask() {
        @Override
        public void run() {
            System.out.println(123);
        }
    });
    return null;
}

問題:

AsyncManager.getManager().execute()メソッドを呼び出すときに導入さscheduledExecutorServiceNULLませんでした。

理由:

@Autowired外部参照から設定する前に、このクラスの構築が完了するまで待つ必要があります。AsyncManager.getManager().execute()メソッドが呼び出されscheduledExecutorServiceても、注入されていないため@Autowired、コンストラクターまたはメソッドに注釈を書き込むことをお勧めします。

2.クラスの初期化順序

上記の問題から、クラスの初期化と初期化シーケンスの問題が拡張されます。

まずテストコードを見てください:

public class Dog {

    public static int a;
    public int b;

    static {
        System.out.println("Static{} a, " + a++);
    }

    {
        System.out.println("{} a, " + a++);
        System.out.println("{} b, " + b++);
    }

    public Dog() {
        System.out.println("Construct a, " + a++);
        System.out.println("Construct b, " + b++);
    }

    public static void show() {
        System.out.println("show() a, " + a++);
    }

    public void display() {
        System.out.println("display() a, " + a++);
        System.out.println("display() b, " + b++);
    }

    public static void main(String[] args) {
        //Dog.show();
        //System.out.println(Dog.a);
        new Dog();
    }
}

mainメソッドで実行new Dog()すると、プログラムの実行結果は次のようになります。

Static{} a, 0
{} a, 1
{} b, 0
Construct a, 2
Construct b, 1

結果は、初期化シーケンスが次のとおりであることを示しています。

静的メンバー変数->静的コードブロック->共通メンバー変数->共通コードブロック->コンストラクター

継承関係がある場合、順序は次のとおりです。親クラスの静的メンバー変数->親クラスの静的コードブロック->サブクラスの静的メンバー変数->サブクラスの静的コードブロック->親クラスの通常メンバー変数->親クラスの通常コードブロック- >サブクラスの通常のメンバー変数->サブクラスの通常のコードブロック->親クラスのコンストラクター->コンストラクター

3.クラスはいつ初期化されますか

  • クラスのインスタンスを作成するとき、オブジェクトは新しい
  • クラスまたはインターフェースの静的変数にアクセスするか、静的変数に値を割り当てます
  • クラスの静的メソッドを呼び出す
  • リフレクション
  • クラスのサブクラスを初期化します(サブクラスの親クラスが最初に初期化されます)
  • JVMの起動時に示される起動クラス、つまり、同じファイル名とクラス名を持つクラス

クラスが初期化されるときは、Java(ClassLoader)のクラス読み込み順序の概要を参照してください。

おすすめ

転載: www.cnblogs.com/lyldelove/p/12710179.html