何千ものクラスを持つかなり大きなアプリケーションにSpringを統合しようとしています。コンポーネントのスキャンが原因で、コンテナの起動に大幅な遅延が発生しています。
「基本パッケージ」で指定されたディレクトリの数は、関係のないディレクトリのスキャンに費やされる時間を減らすために最小限に抑えていますが、初期化のクラスパススキャンの部分にはまだ約1〜2分かかります。
では、スキャンプロセスを最適化する方法はありますか?起動時にクラスパスをスキャンするのではなく、クラスパスの候補をファイルに保存し、コンテナーをファイルから取得することを考えましたが、どこから始めればよいか、それが可能かどうかさえわかりません。
アドバイスは大歓迎です。前もって感謝します。
Edit1:自動生成されたxmlファイルからBean定義を読み込み、Springのブートストラップ時間を9〜10秒に短縮しました。これにより、コンポーネントのクラスパススキャンにSpringが使用するリフレクションAPIが起動遅延の主な原因であることが確認されます。
xmlファイルの生成に関しては、同じ問題のある人に役立つ可能性があるため、ここにコードがあります。
import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.util.ArrayList;
public class ConfigurationWriter {
public ArrayList<String> beanDefinitions = new ArrayList<String>();
public ConfigurationWriter() {
// the context loaded with old fashioned way (classpath scanning)
ApplicationContext context = SpringContainerServiceImpl.getInstance().getContext();
String[] tab = context.getBeanDefinitionNames();
for (int i = 0; i < tab.length - 6; i++) {
Class clazz = context.getType(tab[i]);
String scope = context.isPrototype(tab[i]) ? "prototype" : "singleton";
String s = "<bean id=\"" + tab[i] + "\" class=\"" + clazz.getName() + "\" scope=\"" + scope + "\"/>";
beanDefinitions.add(s);
}
// Collections.addAll(beanDefinitions, tab);
}
@SuppressWarnings("restriction")
public void generateConfiguration() throws FileNotFoundException {
File xmlConfig = new File("D:\\dev\\svn\\...\\...\\src\\test\\resources\\springBoost.xml");
PrintWriter printer = new PrintWriter(xmlConfig);
generateHeader(printer);
generateCorpse(printer);
generateTail(printer);
printer.checkError();
}
@SuppressWarnings("restriction")
private void generateCorpse(PrintWriter printer) {
for (String beanPath : beanDefinitions) {
printer.println(beanPath);
}
}
@SuppressWarnings("restriction")
private void generateHeader(PrintWriter printer) {
printer.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
printer.println("<beans xmlns=\"http://www.springframework.org/schema/beans\"");
printer.println("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"");
printer.println("xmlns:context=\"http://www.springframework.org/schema/context\"");
printer.println("xsi:schemaLocation=\"");
printer.println("http://www.springframework.org/schema/mvc");
printer.println("http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd");
printer.println("http://www.springframework.org/schema/beans");
printer.println("http://www.springframework.org/schema/beans/spring-beans-3.0.xsd");
printer.println("http://www.springframework.org/schema/context");
printer.println("http://www.springframework.org/schema/context/spring-context-3.0.xsd\"");
printer.println("default-lazy-init=\"true\">");
}
@SuppressWarnings("restriction")
private void generateTail(PrintWriter printer) {
// printer.println("<bean class=\"com.xxx.frmwrk.spring.processors.xxxBeanFactoryPostProcessor\"/>");
printer.println("<bean class=\"com.xxx.frmwrk.spring.processors.xxxPostProcessor\"/>");
printer.println("</beans>");
}
}
編集2: Spring 5には、コンテキストの初期化を高速化するための重要な最適化セットが含まれており、コンパイル時に候補コンポーネントのインデックスを生成できる興味深い便利な機能も備えています:Spring Context Indexer
質問:ディレクトリ内のクラスのいくつ(%)がSpring Beanですか?
回答:確かではありません(非常に大きなプロジェクトです)が、xmlファイルとプロパティファイルが別々の場所に分離されているため、90〜100%程度だと私は思います。
問題が本当にコンポーネントのスキャンであり、Beanの初期化プロセス自体ではない場合(そして私はそれを疑っています)、考えられる唯一の解決策は、コンポーネントのスキャンの代わりにSpring XML構成を使用することです。-(XMLファイルを自動的に作成できます)。
しかし、多くのクラスがあり、90%-100%がBeanである場合、スキャンされたファイルの削減により、最大で10%-0%の改善が見られます。
初期化をスピードアップする他の方法を試す必要があります。遅延読み込みまたは遅延読み込み関連のテクニックを使用するか、(そしてそれは冗談ではありません)より高速なハードウェアを使用します(スタンドアロンアプリケーションでない場合)。
Spring XMLを生成する簡単な方法は、元のアプリケーションのようにクラスパススキャンを使用する単純なSpringアプリケーションを作成することです。すべてのBeanが初期化されると、Spring ContextのBeanを反復処理し、Beanが重要なパッケージに属しているかどうかを確認し、このBeanのXML構成をファイルに書き込みます。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加