Подтвердить что ты не робот

Spring проблемы с запуском

Я пытаюсь интегрировать Spring в довольно большое приложение с тысячами классов, и я испытываю огромные задержки, начиная с моего контейнера из-за компонентного сканирования.

Я уже сузил число каталогов, указанных в "базовом пакете", до минимума, чтобы сократить время, затрачиваемое на сканирование нерелевантных каталогов, но часть проверки пути к классу инициализации по-прежнему занимает около 1-2 мин.

Итак, есть ли способ оптимизировать процесс сканирования? Я думал о сохранении пути классов кандидатов в файле и сделать контейнер, а затем получить их из файла, а не сканировать путь класса при каждом запуске, но я не знаю, с чего начать, или если это возможно.

Любые советы очень ценятся. Заранее спасибо.

Изменить. Загрузка определений bean формирует файл с автогенерированным XML файлом, сокращает время начальной загрузки Spring до 9 ~ 10 секунд, что подтверждает, что отражение api, используемое Spring для класса компонентов -path - основной источник задержек запуска.
Что касается генерации 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>");
    }

}
4b9b3361

Ответ 1

Вопрос: Сколько (в%) классов в каталогах Spring Beans?

Ответ: Я не уверен (это действительно большой проект), но из того, что я видел, я считаю, что он составляет от 90 до 100%, поскольку файлы xml и properties изолированы в разных местах)

Если проблема в самом деле - это проверка компонентов, а не сам процесс инициализации bean (и я очень сомневаюсь в этом), то единственным решением, которое я могу себе представить, является использование конфигурации Spring XML вместо сканирования компонентов. - (Можете ли вы создать файл XML автоматически).

Но если у вас много классов, а 90% - 100% из них Beans, то сокращение отсканированных файлов будет иметь максимальное улучшение на 10% -0%.

Вы должны попробовать другие способы ускорить вашу инициализацию, использовать ленивую загрузку или любые ленивые методы, связанные с загрузкой, или (и это не шутка) использовать более быстрое оборудование (если это не отдельное приложение).


Простым способом генерации XML Spring является создание простого приложения Spring, которое использует сканирование пути к классу, как и исходное приложение. После инициализации Beans он выполняет итерацию через Beans в контексте Spring, проверьте, принадлежит ли bean к важному пакету и записывает XML Config для этого bean в файл.

Ответ 2

Не так много вы можете сказать о производительности там, я думаю, вас не интересует запуск в производственной среде, но время запуска ваших тестов *. Два совета:

  • Проверьте, что ваш тестовый appcontext использует только минимально необходимые компоненты вашего приложения.
  • вместо того, чтобы иметь список директив для проверки компонентов, используйте один с разделенным запятой значением следующим образом: base-package = "com.package.one, com.package.two..."

Ответ 3

Автоматическое обнаружение аннотированных классов в настоящее время требует сканирования всех классов в указанных пакетах и ​​может занять много времени, известной проблемы текущего механизма загрузки классов.

Java 9 поможет здесь с Jigsaw.

Из модуля Java Platform Module Системные требования Марка Рейнольда, http://openjdk.java.net/projects/jigsaw/spec/reqs/:

Эффективное обнаружение аннотаций - Должно быть возможно идентифицировать все файлы классов в артефакте модуля, в котором присутствует конкретная аннотация, без фактического чтения всех файлов классов. Во время выполнения должно быть возможно идентифицировать все классы в загруженном модуле, в котором присутствует конкретная аннотация, без перечисления всех классов в модуле, если аннотация была сохранена для времени выполнения. Для эффективности может потребоваться указать, что только определенные аннотации должны быть обнаружены таким образом. Одним из потенциальных подходов является увеличение определения модулей с помощью индекса аннотаций, присутствующих в модуле, вместе с указанием элементов, к которым применяется каждая аннотация. Чтобы ограничить размер индекса, будут включены только аннотации, которые сами аннотируются с помощью новой мета-аннотации, например @Indexed.

Ответ 4

Единственное, что приходит мне на ум, помимо сокращения сканируемых каталогов, - это использование lazy bean initialization. Пусть это может помочь, если у вас много beans

Ответ 5

Я знаю, что это старый вопрос, и, как вы увидите, в то время ситуация была другой, но, надеюсь, это может помочь другим исследовать эту проблему, как и я.

В соответствии с этим ответом на другой вопрос аннотация @ComponentScan теперь поддерживает флаг lazyInit, что должно помочь сократить время запуска.

fooobar.com/questions/173859/...

Примечание. Ваше редактирование заставило его походить на то, что переключение на XML само по себе было волшебством. Тем не менее, взглянув ближе на код, вы имели default-lazy-init="true". Интересно, была ли это истинная причина.

Ответ 6

Вместо сканирования компонентов вы можете использовать Spring конфигурацию контейнера на Java.

В сравнении с конфигурацией на основе XML конфигурация контейнера на основе Java безопасна для типов.

Но прежде всего вы должны проверить, достаточно ли пути отслеживания вашего компонента, чтобы они не включали классы сторонних библиотек.