98

春のMVCアプリケーションでは、次のアプローチを使用して、サービスクラスの1つで変数を初期化します。

ApplicationContext context = 
         new ClassPathXmlApplicationContext("META-INF/userLibrary.xml");
service = context.getBean(UserLibrary.class);

UserLibraryは、アプリケーションで使用しているサードパーティのユーティリティです。上記のコードは、「context」変数に対する警告を生成します。警告を以下に示します。

Resource leak: 'context' is never closed

警告がわかりません。アプリケーションはSpringMVCアプリケーションであるため、アプリケーションの実行中にサービスを参照するときに、コンテキストを実際に閉じたり破棄したりすることはできません。警告が私に伝えようとしているのは正確には何ですか?

4

17 に答える 17

95

アプリ コンテキストはResourceLoader(つまり、I/O 操作) であるため、ある時点で解放する必要があるリソースを消費します。これはAbstractApplicationContextwhich implementsの拡張でもありますClosable。したがって、メソッドがあり、 try-with-resources ステートメントでclose()使用できます。

try (ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("META-INF/userLibrary.xml")) {
  service = context.getBean(UserLibrary.class);
}

実際にこのコンテキストを作成する必要があるかどうかは別の問題です (リンクしています)。それについてはコメントしません。

アプリケーションが停止するとコンテキストが暗黙的に閉じられるのは事実ですが、それだけでは十分ではありません。Eclipseは正しいです。クラスローダーのリークを避けるために、他の場合には手動で閉じるための措置を講じる必要があります。

于 2013-01-06T22:21:53.117 に答える
40

close()ApplicationContextインターフェイスで定義されていません。

警告を安全に取り除く唯一の方法は次のとおりです

ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(...);
try {
    [...]
} finally {
    ctx.close();
}

または、Java7では

try(ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(...)) {
    [...]
}

基本的な違いは、コンテキストを明示的に(つまり、を使用してnew)インスタンス化するため、インスタンス化するクラスがわかっているため、それに応じて変数を定義できることです。

AppContextをインスタンス化していない場合(つまり、Springが提供するものを使用している場合)、AppContextを閉じることができませんでした。

于 2013-02-12T10:16:00.153 に答える
3

まったく同じ警告が表示ApplicationContextされたとしても、メイン関数の外側private staticで ta-da として宣言するだけで、問題は修正されました。

public class MainApp {
    private static ApplicationContext context;

    public static void main(String[] args) {
        context = new ClassPathXmlApplicationContext("Beans.xml");

        HelloWorld objA = (HelloWorld) context.getBean("helloWorld");

        objA.setMessage("I'm object A");
        objA.getMessage();

        HelloWorld objB = (HelloWorld) context.getBean("helloWorld");
        objB.getMessage();
    }
}
于 2014-03-13T05:34:35.997 に答える
2

キャストは、この問題の正しい解決策です。以下の行を使用して同じ問題に直面しました。 ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);

警告を解決するには、ctx以下のようにオブジェクトをダウンキャストしてから閉じます。 ((AnnotationConfigApplicationContext) ctx).close();

于 2019-03-22T18:59:33.227 に答える
1

コンテキストを ConfigurableApplicationContext にダウンキャストします。

((ConfigurableApplicationContext)context).close();
于 2014-08-07T09:26:37.960 に答える
1
Object obj = context.getBean("bean");
if(bean instanceof Bean) {
    Bean bean = (Bean) obj;
}

私の場合、リークは消えます

于 2016-04-20T11:19:05.653 に答える
1

これは私にとって最もうまくいきました。

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


public class Test {

     private static ApplicationContext con;

     public static void main(String[] args) {

         con = new ClassPathXmlApplicationContext("config.xml");

         Employee ob = (Employee) con.getBean("obj");
         System.out.println("Emp Id " + ob.getEmpno());
         System.out.println("Emp name " + ob.getEmpname());
    }
}
于 2018-04-23T16:14:38.583 に答える
0
import org.springframework.context.ConfigurableApplicationContext;

((ConfigurableApplicationContext)ctx).close();
于 2016-10-02T09:59:27.743 に答える
0

ClassPathXmlApplicationContextを使用している場合は、使用できます

((ClassPathXmlApplicationContext) context).close();

リソースリークの問題を解決します。

AbstractApplicationContextを使用している場合は、これを close メソッドでキャストできます。

((AbstractApplicationContext) context).close();

アプリケーションで使用するコンテキストのタイプによって異なります。

于 2015-08-09T21:05:37.917 に答える
0

このリンク [春のコア jar ファイルをダウンロード][1] [1]: https://static.javatpoint.com/src/sp/spcorejars.ジップ

于 2020-06-25T10:50:58.223 に答える
-1

close メソッドが ConfigurableApplicationContext インターフェースに追加されたので、それにアクセスするためにできる最善の方法は次のとおりです。

ConfigurableApplicationContext context = new ClassPathXmlApplicationContext(
                "/app-context.xml");

// Use the context...

context.close();
于 2015-04-22T18:50:52.273 に答える