当前位置: 首页 > 面试题库 >

春季启动性能问题

朱啸
2023-03-14
问题内容

我试图将Spring集成到具有数千个类的大型应用程序中,并且由于组件扫描,我在启动容器时遇到了巨大的延迟。

我已经将“基本软件包”中指定的目录数量缩小到最小,以减少扫描无关目录所浪费的时间,但是初始化的类路径扫描部分仍然需要大约1-2分钟。

那么,有没有一种方法可以html" target="_blank">优化扫描过程?我曾考虑过将候选类路径存储在文件中,然后使容器从文件中获取,而不是每次启动时都扫描类路径,但是我真的不知道从哪里开始,或者甚至可能。

任何建议深表感谢。提前致谢。

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中的目录中有多少类(以百分比计)?

答:我不太确定(这是一个非常大的项目),但是据我所见,我相信它大约在90%到100%之间,因为xml和属性文件被隔离在不同的位置)

如果问题确实是组件扫描而不是bean初始化过程本身(我对此表示高度怀疑),那么我能想到的唯一解决方案是使用Spring
XML配置而不是组件扫描。-(可以自动创建XML文件)。

但是,如果您有很多类,并且90%-100%是Bean,那么减少扫描文件的最大效率将是10%-0%。

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

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



 类似资料:
  • 问题内容: 我正在使用logback库在spring boot项目中实现日志记录。我想根据我的spring配置文件(属性“ spring.pofiles.active”)加载不同的日志记录配置文件。我有3个文件:logback-dev.xml,logback- inte.xml和logback-prod.xml。我正在使用Spring Boot版本1.2.2.RELEASE。 如您在Spring

  • 问题内容: 我的Maven依赖项出了什么问题。当我包含JPA时,我会列出pf例外 这是我的Maven依赖项 我的例外 和我的源代码 因此,我没有任何想法(不幸的是,没有示例)如何运行Spring boot和休眠两者。 问题答案: 您是否为数据源设置了或?这是一个例子: 有关可以在何处放置配置文件以及如何配置应用程序以处理任何目录中的属性文件的说明,请参阅此链接以获取更多信息。

  • 问题内容: 我目前正在使用Spring编写API后端,我想使用Spring Boot部署到生产服务器上。 如果我在Eclipse中运行后端以编译为War(在Maven中指定),并使用Tomcat 7,则它可以正常运行。 但是,当我想部署到服务器时,我正在使用Spring Boot。 应用程序 pom.xml 当我将整个项目复制到Linux服务器上并运行 maven package时 ,代码可以毫无

  • 问题内容: 我有以下Spring Security配置: 我期望以下逻辑:未经身份验证的用户将被重定向到。Spring会显示默认的Tomcat 403页面,而不是该页面。我也尝试过自定义,尽管没有成功。 如何在访问失败时实施自定义逻辑? 问题答案: AccessDeniedHandler仅适用于经过身份验证的用户。未经身份验证的用户的默认行为是重定向到登录页面(或适用于所使用的身份验证机制的任何内

  • 问题内容: 在应用程序中,我可以使用以下命令指定自定义日志文件: 但是,如果我不指定一个,它会去哪儿? 我在以下任何文件夹中找不到它: 我 不 具备或任何其他日志记录的依赖。 我希望有类似的东西,因为默认配置运行嵌入式Tomcat: 问题答案: Spring Boot使用Commons Logging进行所有内部日志记录,但是使底层日志实现保持打开状态。 提供了Java Util Logging,

  • 问题内容: 我是spring的新手,我使用https://start.spring.io/创建了一个新的spring boot项目,没有更多依赖关系,解压缩了zip文件并在IntelliJ IDEA中打开了该项目。我没有做任何进一步的配置。我现在正在尝试使用@PostConstruct方法设置bean-但是,该方法从未被spring调用。 这些是我的课程: SpringTestApplicatio