Springコンテナの警告:リソースリークを解決する方法:「applicationContext」が閉じられることはなく、Springコンテナの3つの閉じた原則の分析


序文

Spring IoCコンテナーのApplicationContextを初期化し、構成ファイルをロードした後、コンテナーを処理しない場合、直感的に最初に表示されるのは、IDEの警告です。リソースリーク:「コンテキスト」は決して閉じられません。第二に、他にどのような問題がありますか?このような問題をどのように解決しますか?この記事では、このタイプの問題に対する3つの異なる解決策を提案し、1つの問題から1つのタイプの問題を解決できるようにします。

ここに画像の説明を挿入します


1つは、春のコンテナ警告の生成です

1.1、プロジェクトシーン

Spring IoCコンテナーのApplicationContextを初期化し、構成ファイルをロードして、Beanのインスタンスを作成しました。コードは次のとおりです。

public class Test {
    
    
	public static void main(String[] args) {
    
    
		// 初始化Spring容器applicationContext,加载配置文件
		ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
		// 通过容器获取test实例
		TestDao dao = (TestDao) context.getBean("test");// test为配置文件中的id
		dao.sayHello();
	}
}

ここでは、コンテナの使用が終了した後、コンテナが処理されていないことがわかり、IDEで次のように警告されますResource leak: 'context' is never closed

プロンプト:コンテナは閉じられていません。警告の内容を次の図に示します。

ここに画像の説明を挿入します

第二に、Springコンテナを閉じなかった場合の結果の分析

2.1、肉眼で見える警告

強迫性障害の場合、これはあなたを殺すつもりではありませんか?私は良いプロジェクトを持っています、あなたは私に感嘆符を与えますか?いいえ、解決する必要があります。

ここに画像の説明を挿入します
ショートカットキーを使用してカーソル行の問題をすばやく特定し、プロンプトに従って次のコードを追加します。これはどういう意味ですか?警告を無視します。警告を削除したいだけの場合は、読み進める必要はありません。この方法は完全にあなたを満足させることができます。

@SuppressWarnings("resource")

2.2、結果として生じるメモリリーク

コンテナが閉じられていない場合、メモリリークが発生する可能性があります。これに関しては、次のような質問がある場合があります。
ここに画像の説明を挿入します

JavaにはGC(ガベージコレクション)メカニズムがありませんか?どのようにしてメモリリークを引き起こす可能性がありますか?心配しないで、段階的に分析してみましょう。

2.2.1。メモリリークとは何ですか?

メモリリークとは、使用されなくなったオブジェクトまたは変数がメモリで占有されていることを意味します。

2.2.2メモリリークを判断する方法は?

Javaでメモリリークをチェックするには、プログラムの各ブランチの実行を最後まで完了してから、それが使用されているかどうかを確認する必要があります。使用されていない場合は、オブジェクトがメモリリークであると判断できます。

2.2.3、JavaのGC(ガベージコレクション)

Java仮想マシンJVMは、メモリから使用されなくなったオブジェクトまたは変数を再利用して、メモリを解放します。
(JavaのGCの内容はここでは繰り返されません。私のJavaコラムで確認できます)

2.2.4、Javaでメモリリークを引き起こす状況

  1. 寿命の長いオブジェクト寿命の短いオブジェクトへの参照を保持している場合、メモリリークが発生する可能性があります。寿命の短いオブジェクトは不要になりましたが、寿命の長いオブジェクトは参照を保持し続けるため、リサイクルできません。たとえば、キャッシュシステム。オブジェクトをロードしてキャッシュシステムに配置します。オブジェクトを使用することはありませんが、常にキャッシュによって参照されるため、リサイクルされたり、キャッシュリークが発生したりすることはありません。
  2. オブジェクトがHashSetコレクションに格納されている場合、このオブジェクトのハッシュ値の計算に使用されるプロパティは変更できません。それ以外の場合、オブジェクトの変更されたハッシュ値は、HashSetコレクションに追加されたばかりのハッシュ値とは異なります。この時点で、現在のオブジェクトの参照がパラメーターとして使用され、containsメソッドを使用してかどうかを判断する場合オブジェクトが存在する場合、見つからないオブジェクトを返します。結果。これにより、HashSetだけから現在のオブジェクトを削除できなくなり、メモリリークが発生します。

2.2.5、Springコンテナによって引き起こされたメモリリークが閉じられない

Spring IoCコンテナーを開始した後、JVMは、オブジェクトまたは変数をリサイクルするようなオブジェクトまたは変数をリサイクルできません。Springコンテナのライフサイクルは、初期化されたすべてのBeanを管理するために使用されるため、比較的長く、そのライフサイクルはBeanの後です(特にSpringのライフサイクルについては、後で説明します)。閉じない場合。やがて、それはメモリを占有し、JVMの効率を低下させ、メモリリークを引き起こします。もちろん、これは当社の開発仕様を満たしていません。

3. Springコンテナを手動で閉じる方法(最も一般的に使用される3.2)

コンテナとストリームを閉じる問題をどのように解決できますか?3つの方法があります。1つ目は最も便利な方法、2つ目は開発で最も一般的に使用される方法、3つ目は最も単純で失礼な方法です。必要に応じて使用できます。

3.1、context.close();

Springコンテナの処理はScannerストリームに似ています。Scannerストリームを閉じるという考えに従い、close()メソッドを呼び出し、以下に示すようにcloseコードを追加します。

context.close();

この時点でもエラーは報告されています。プロンプトによるThe method close() is undefined for the type ApplicationContextと、close()メソッドがSpring IoCコンテナで直接定義されていないことがわかります。ショートカットキーを使用して、カーソル行で問題をすばやく特定します。に示すように、コンテキストに型変換を追加します。次の図:

ここに画像の説明を挿入します
このとき、次のコード行が追加されました。

((AbstractApplicationContext) context).close();

このようにして、Springコンテナをシャットダウンできます。それcontext.close();は問題を解決します。

3.2、((ConfigurableApplicationContext)context).close();

Springコンテナを閉じるメソッドclose()は、ApplicationContextのConfigurableApplicationContextサブクラスで定義されているSpringで定義されていますでは、コンテナを閉じるためにどのようにすばやく呼び出すのでしょうか。

3.2.1.org.springframework.context.support.AbstractApplicationContextパッケージをインポートします

ショートカットキーを使用して、最初に3.1の手順を実行し、次に3.1のシャットダウンコードを削除し、シャットダウンコードを1((AbstractApplicationContext) context).close();回書き直しますcontext.close();。この時点で、強制的に回すと、追加のタイプのConfigurableApplicationContextがあることがわかります。次の図に示すように、これを選択します。

ここに画像の説明を挿入します

:ConfigurableApplicationContextの強制変換タイプが表示される前に、org.springframework.context.support.AbstractApplicationContextパッケージをインポートする必要があります。

現時点では、シャットダウンコードは次のとおりです。

((ConfigurableApplicationContext) context).close();

3.2.2、冗長ガイドパッケージを削除します

このとき、上記のorg.springframework.context.support.AbstractApplicationContextを含め、プロンプトに従って冗長ガイドパッケージを削除できます。

概要:この書き込み方法は、開発でSpringコンテナーを手動でシャットダウンするために最も一般的に使用される方法です。

3.3。オブジェクトの公開宣言を取得する方法を使用する

3.3.1、Method Class.getMethod(String name、Class <?>…parameterTypes)

この補足メソッドの機能は、オブジェクトによって宣言されたパブリックメソッドを取得することです。これは、開発中にオブジェクトメソッドを取得するための一般的なメソッドでもあります。

Method Class.getMethod(String name, Class<?>... parameterTypes)

パラメータの説明

  1. パラメータ名は、現在のメソッドの名前を取得します。
  2. parameterTypesは、宣言の順序でメソッドのパラメータータイプを識別します。
  3. オブジェクト内のメソッドの仮パラメーターがint型の場合、parameterTypesはint.classです。

例は次のとおりです。

person.getClass().getMethod("Speak", null);
//获得person对象的Speak方法,因为Speak方法没有形参,所以parameterTypes为null

person.getClass().getMethod("run", String.class);
//获得person对象的run方法,因为run方法的形参是String类型的,所以parameterTypes为String.class

3.3.2。この方法を使用してSpringコンテナを閉じる方法

3.3.1の内容によると、コンテキストオブジェクトメソッドclose()を取得し、コンテキストコンテナオブジェクトを呼び出すことができます(null値は省略されます)。コードは次のとおりです。

context.getClass().getMethod("close").invoke(context);

ただし、このメソッドを使用する場合は、例外を処理する必要があることに注意してください。ここで例外をキャプチャします。完全なコードは次のとおりです。

package cn.bailu.ch1.test;

import java.lang.reflect.InvocationTargetException;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import cn.bailu.ch1.dao.TestDao;

public class Test {
    
    
	public static void main(String[] args) {
    
    
		// 初始化Spring容器applicationContext,加载配置文件
		ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
		// 通过容器获取test实例
		TestDao dao = (TestDao) context.getBean("test");// test为配置文件中的id
		try {
    
    
			context.getClass().getMethod("close").invoke(context);
		} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException
				| SecurityException e) {
    
    
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		dao.sayHello();
	}
}

総括する

この記事では、Spring IoCコンテナを閉じる方法に関する3つの一般的な解決策を紹介します。最初の方法が最も簡単で、2番目の方法が開発で最も一般的に使用されています。この方法は、広範囲にわたって調査されています。 Springソースコード、内部のメソッドを知るためのソースコードを知っています、そして3番目の方法は最も単純で失礼であり、他のオブジェクトのメソッドを取得するときにもより一般的に使用されます。このメソッドはJavaの基本的な知識を調べます。コードの理解のレベルは、あなた自身のニーズに基づいています。簡単なケースはあなたの基本的なスキル、しっかりした基盤を示しています、ソースコードをもっと見てください!

ここに画像の説明を挿入します


応援よろしくお願いします。疲れを知らないプログラマー、バイルです。この投稿がすべての人に役立つことを願っています。そして、すべての人のワンクリック3接続を歓迎します。質問、提案、補足がある場合は、投稿の下部にメッセージを残して、より多くの人を助けることができます!
詳細情報WeChat検索パブリックアカウントWDeerCodeコードサークル

おすすめ

転載: blog.csdn.net/qq_22695001/article/details/109747971