java - Spring启动性能问题

标签 java spring spring-mvc classpath bootstrapping

我正在尝试将 Spring 集成到一个包含数千个类的相当大的应用程序中,但由于组件扫描,我在启动容器时遇到了巨大的延迟。

我已经将“base-package”中指定的目录数量缩小到最少,以减少扫描无关目录所浪费的时间,但是初始化的class-path扫描部分仍然需要大约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

最佳答案

Question: How many (in %) of the classes in the directories are Spring Beans?

Answer: I'm not really sure (it's a really big project) , but from what i saw i believe it's arround 90 to 100%, since xml and properties files are isolated in separate locations)

如果问题真的是组件扫描而不是 bean 初始化过程本身(我非常怀疑),那么我能想到的唯一解决方案是使用 Spring XML 配置而不是组件扫描。 - (希望您可以自动创建 XML 文件)。

但是如果你有很多类,并且其中 90% - 100% 是 Beans,那么扫描文件的减少将有 10%-0% 的最大提升。

您应该尝试其他方法来加快初始化速度,可以使用延迟加载或任何延迟加载相关技术,或者(这不是开玩笑)使用更快的硬件(如果它不是独立的应用程序)。


生成 Spring XML 的一种简单方法是编写一个简单的 spring 应用程序,该应用程序使用类路径扫描,就像您的原始应用程序一样。在所有的 Bean 初始化完成后,遍历 Spring Context 中的 Bean,检查该 bean 是否属于重要包,并将该 bean 的 XML Config 写入文件。

关于java - Spring启动性能问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5947713/

相关文章:

java - 静态内容未从 Spring Boot 应用程序加载到 JSP 页面中

java - 为什么我们使用 Simple LoadTimeWeaver?

java - 为什么 HIbernate 的 PESEL validator 不起作用?

java - java执行时bat文件没有按预期执行

Java Controller 需要什么代码?

spring - Spring Cloud 版本中的 Camden.RELEASE 表示什么?

java - session 变量未在 Spring 中设置

spring - 没有名为 'transactionManager' 的可用 bean

java - 对于基于图 block 的横向卷轴游戏,如何让角色在跳跃后遇到方 block 时停止?

java - Spring Security XML 配置与 Java 配置