Spring application lazy loading method based on container lifecycle control
Patent Information
- Application Number
- CN202611152707.3
- Authority / Receiving Office
- CN · China
- Patent Type
- Applications(China)
- Current Assignee / Owner
- Filing Date
- 2026-07-31
- Publication Date
- 2026-08-28
AI Technical Summary
然而现有懒加载机制存在以下根本性弊端,导致其在实际应用中效果有限,具体如下:
本发明通过自定义懒加载容器拦截全量Bean同步实例化流程,彻底摆脱了Spring原生@Lazy注解和全局懒加载配置的局限性,实现了对包括第三方组件在内的所有Bean的懒加载统一管控。
Smart Images

Figure CN122653712A_ABST
Abstract
Description
Technical Field
[0001] This invention relates to the fields of software engineering and microservice architecture technology, and in particular to a lazy loading method for Spring applications based on container lifecycle control. Background Technology
[0002] With the widespread adoption of microservices, Kubernetes elastic scaling, and edge computing, Spring Boot, as a mainstream development framework, is widely used in business development. Application startup speed directly impacts development and debugging efficiency, container cluster deployment density, and elastic scaling capabilities in cloud-native scenarios. To improve startup performance, Spring provides two native lazy loading solutions: one is to implement lazy initialization of a single container-managed object (Bean) based on the lazy loading annotation (@Lazy); the other is to configure the global parameter spring.main.lazy-initialization=true to enable global lazy loading, thereby achieving lazy initialization of container-managed objects. However, existing lazy loading mechanisms have the following fundamental drawbacks, which limit their effectiveness in practical applications, as follows: 1. Limited scope of control, unable to cover third-party components: Lazy loading annotations only apply to container-managed objects explicitly annotated by developers. Most third-party starters are initialized directly in the auto-configuration class through the Bean annotation (@Bean) method or constructor. Their loading behavior is not controlled by lazy loading annotations, forming a forced wake-up mechanism of "loading upon introduction". 2. The native eager loading mechanism is prone to triggering full-chain cascading initialization: The Spring container adopts the singleton container-managed object eager loading strategy by default. Once a lazy container-managed object proxied by the lazy loading annotation is called by an eager container-managed object created synchronously during the startup phase, all container-managed objects in its dependency tree will be recursively initialized, causing lazy loading to fail instantly on the first access, making the previous optimization results zeroed out at once. 3. Third-party components are loaded earlier and are not subject to application layer lazy loading control: Third-party starters rely on the spring.factories mechanism to load configuration classes and register container-managed object definitions in the early stages of container refresh. Component initialization actions are executed in the middle of startup and are not constrained by the application layer lazy loading mechanism, making it difficult for developers to adjust their loading timing. Summary of the Invention
[0003] The purpose of this invention is to address the shortcomings of existing technologies by proposing a lazy loading method for Spring applications based on container lifecycle control.
[0004] To achieve the above objectives, the present invention adopts the following technical solution: This invention also proposes a lazy loading method for Spring applications based on container lifecycle control, comprising the following sub-steps: S1: Load a custom container factory via the SPI mechanism, create a custom lazy-loaded container, and set it as the default container context; S11: The startup core class loads the custom container factory via the SPI service loading mechanism; When a Spring application starts, its built-in startup core class scans the META-INF / spring.factories configuration file under the classpath through the Java standard SPI service loading mechanism. The META-INF / spring.factories configuration file is the SPI configuration file, and reads all SPI extension implementation classes registered in the SPI configuration file. The SPI configuration file pre-registers a custom container factory class. After the core class instantiates all SPI extension implementation classes, it selects the custom container factory instance generated by the custom container factory class from the generated SPI extension implementation instances and caches the custom container factory instance as the container factory instance used by the current Spring application. S12: The startup core class calls the creation method of the custom container factory to generate a custom lazy-loaded container instance; The startup core class calls the creation method corresponding to the cached container factory instance. After being overridden, the creation method corresponding to the container factory instance no longer returns the default native container of the Spring framework, but builds and returns a custom lazy-loaded container instance. The custom lazy loading container instance on which the custom lazy loading container instance is generated inherits from the Spring native annotation configuration container; S13: The startup core class sets a custom lazy-loaded container instance as the application's default container context; After the startup core class receives the returned custom lazy-loaded container instance, it sets the custom lazy-loaded container instance as the default container context used by the current Spring application.
[0005] S2: Execute the standard refresh process of the Spring container to complete the loading of Bean definitions and the instantiation and registration of BeanPostProcessor; After a custom lazy-loaded container instance is set as the default container context, the standard Spring container refresh process is executed, i.e., the refresh method is called. It reuses Spring's native annotation configuration to configure the execution logic within the container, and sequentially completes the standard pre-initialization operations of the container, such as BeanFactory initialization preparation, Bean definition loading, BeanFactoryPostProcessor execution, BeanPostProcessor instantiation and registration, message source initialization, event broadcaster initialization and listener registration.
[0006] S3: Execute to the finishBeanFactoryInitialization step, skipping the full pre-instantiateSingletons pre-instantiation method of BeanFactory; In a custom lazy-loaded container, the finishBeanFactoryInitialization method is overridden to only perform operations such as ConversionService initialization, embedded value resolver registration, LoadTimeWeaverAware initialization, and BeanFactory configuration freezing, and no longer executes the original BeanFactory preInstantiateSingletons batch pre-instantiation process.
[0007] S4: Execute until the refresh completion phase, intercept the container ready event publication, and the main thread returns quickly; The `finishRefresh` method is overridden in a custom lazy-loading container beforehand. Within the overridden `finishRefresh` method, the parent class's `finishRefresh` method is called to clear the resource cache. The parent class is a Spring native annotation configuration container. The `publishEvent` event publishing method is also overridden, and the original event publishing execution code within the overridden `publishEvent` event publishing method is cleared, making the overridden `publishEvent` event publishing method an empty logic. After the finishBeanFactoryInitialization step is completed, the standard refresh process of the Spring container enters the finishRefresh step. In the finishRefresh step, the Spring native annotation configuration container performs resource cache cleanup and publishes container ready events. The Spring native annotation configuration container executes the execution logic, performs resource cache cleanup, publishes container ready events, and marks the container startup as complete. When the publish container ready event is triggered during the execution of the parent class finishRefresh method, the publishEvent method, which has been overridden and set to have empty logic, is executed. The publishEvent method does not perform any event publishing actions, thereby intercepting the event publishing operation in the main thread. The main thread does not perform any event publishing operations, but only completes resource cache cleanup and other operations before returning immediately. After the finishRefresh step is completed, the standard refresh process of the Spring container ends, the main thread completes the container startup, and the Spring application provides services to the outside world.
[0008] S5: After the application starts, start a background asynchronous thread to load the Bean and publish the container ready event; By starting an asynchronous background thread, all Bean instantiations are completed in the background; S51: The background asynchronous thread executes the preInstantiateSingletons method of BeanFactory to complete the instantiation of all beans; The container starts a separate background asynchronous thread, in which the preInstantiateSingletons method of BeanFactory is executed. This method iterates through all non-lazy-loaded singleton Bean definitions in the Bean definition registry and executes instance creation, dependency injection, and complete initialization lifecycle callbacks one by one. S52: A background asynchronous thread publishes a container ready event; After the background asynchronous thread completes the instantiation of all business beans in BeanFactory's preInstantiateSingletons, the background asynchronous thread calls the parent class's publishEvent method to publish a container ready event, notifying all pre-registered event listeners to execute business warm-up, initialization and other processing logic. The parent class is the Spring native annotation configuration container that the custom lazy loading container inherits from.
[0009] Compared with the prior art, the beneficial effects of the present invention are as follows: This invention completely eliminates the limitations of Spring's native @Lazy annotation and global lazy loading configuration by intercepting the synchronous instantiation process of all beans through a custom lazy loading container, and achieves unified management and control of lazy loading for all beans, including third-party components.
[0010] Spring's native lazy loading mechanism has a fundamental flaw: the `@Lazy` annotation only applies to beans explicitly annotated by the developer. Most third-party starters initialize beans directly in their auto-configuration classes via `@Bean` methods or constructors, and their loading behavior is not controlled by lazy loading annotations, creating a forced "load upon import" mechanism. While global lazy loading configuration (`spring.main.lazy-initialization=true`) can cover more beans, it cannot finely control the loading order, and its priority conflict with `@Lazy` annotations can easily lead to configuration chaos. This invention replaces the native Spring container with a custom lazy loading container through the SPI mechanism in the earliest stage of application startup, and rewrites the bean factory initialization and cleanup logic to intercept the full synchronous instantiation process of `preInstantiateSingletons`. This ensures that all components (including all beans generated by third-party starters via auto-configuration and `@Bean` methods) are no longer forcibly instantiated during startup, thus completely solving the problem of managing "load upon import" third-party dependencies.
[0011] Spring's native container uses a singleton bean rush loading strategy by default. Once a lazy bean proxied by @Lazy is called by a rush-loaded bean created synchronously during startup, all beans in its dependency tree will be recursively initialized, causing lazy loading to fail instantly on the first access. At the same time, if there are circular dependencies between beans after enabling global lazy loading, no error will be reported during startup, but it will be exposed when a certain interface is called for the first time at runtime. The problem is delayed to the production environment, which is more dangerous than an error reported at startup. This invention is completely transparent to business code and third-party components, requiring no modification to business code, configuration files or third-party plugin source code, and is compatible with various mainstream versions of the Spring framework while fully preserving the semantics of Spring's native annotations. All modifications in this invention are implemented by customizing the container to inherit from the native Spring container and overriding key lifecycle methods, without intruding on business logic. Developers do not need to add the `@Lazy` annotation to business classes or adjust any configuration files. Third-party starters can be uniformly managed by the lazy loading mechanism of this invention without any modifications. At the same time, this invention fully reuses the singleton pre-instantiation execution logic built into the Spring framework, which can fully trigger the entire lifecycle callback of the Bean, ensuring the correct and reliable operation of various lazy-loaded business components. Attached Figure Description
[0012] Figure 1 The flowchart illustrates the steps of a Spring application lazy loading method based on container lifecycle control proposed in this paper. Detailed Implementation
[0013] To provide a further understanding of the purpose, structure, features, and functions of the present invention, detailed descriptions are provided below with reference to specific embodiments.
[0014] Please refer to the reference. Figure 1 This invention also proposes a lazy loading method for Spring applications based on container lifecycle control, comprising the following sub-steps: S1: During the application startup phase, a custom container factory is loaded via the SPI mechanism, a custom lazy-loaded container is created and set as the default container context; This step is executed at the very earliest stage of the Spring application startup and is used to replace the native Spring container with the custom lazy-loaded container of this invention. S11: The startup core class loads a custom container factory via the SPI mechanism; When a Spring application starts, its built-in startup core class begins the application context creation and preparation process. In the creation and preparation process, the startup core class first scans the META-INF / spring.factories configuration file under the classpath through the Java standard SPI service loading mechanism. The META-INF / spring.factories configuration file is the SPI configuration file, and reads all the SPI extension implementation classes registered in the SPI configuration file. Since the custom container factory class has been pre-registered in the SPI configuration file, the container factory loaded by the startup core class through the SPI mechanism is no longer the default factory built into Spring, but the custom container factory provided by the present invention; after loading, the startup core class caches the custom container factory as the container factory instance used by the current application. S12: The startup core class calls the creation method of the custom container factory to generate a custom lazy-loaded container instance; When the core class progresses to the "create application context" stage, it calls the creation method of the currently cached container factory instance. After the creation method is overridden, it no longer returns the default native container of the Spring framework, but instead creates a custom lazy-loaded container instance and returns it. The custom lazy loading container instance on which the custom lazy loading container instance is generated inherits from the Spring native annotation configuration container, thus fully retaining all the core capabilities of the Spring framework such as component scanning, annotation parsing, and bean definition registration, while allowing its key lifecycle methods to be overridden and extended. S13: The startup core class sets the custom lazy-loaded container as the application's default container context; After the startup core class receives the custom lazy-loaded container instance returned by the custom container factory, it immediately sets the custom lazy-loaded container instance as the default container context used by the current Spring application. From then on, all subsequent operations related to the container lifecycle (including Bean definition loading, Bean instantiation, container refresh, etc.) are executed in the custom lazy-loaded container instance. S2: Execute the Spring standard refresh process to complete the loading of Bean definitions and the registration of BeanPostProcessor; After the custom lazy-loaded container is set as the default container context, the standard refresh process of the Spring container, namely the refresh method, is executed. In the standard refresh process of the Spring container, the Spring container sequentially completes the standard steps such as the preparation of BeanFactory, scanning and loading of Bean definitions, calling BeanFactoryPostProcessor, instantiation and registration of BeanPostProcessor, initialization of message source, initialization of event broadcaster, and registration of listener. The above steps completely reuse the native logic of Spring, and this invention does not make any changes. The changes to the refresh process in this invention begin with the finishBeanFactoryInitialization step.
[0015] S3: Execute to the finishBeanFactoryInitialization stage, skipping the full pre-instantiateSingletons pre-instantiation method of BeanFactory; In the Spring container's refresh process, after the above standard steps are completed, the container proceeds to the finishBeanFactoryInitialization step. `finishBeanFactoryInitialization` is the last step in the Spring container refresh process to instantiate beans. In this step, the Spring native container completes basic operations such as ConversionService initialization, embedded value resolver registration, LoadTimeWeaverAware initialization, and BeanFactory configuration freezing. Then, it calls the `preInstantiateSingletons` method of BeanFactory to perform batch pre-instantiation of all non-lazy-loaded singleton beans in the bean definition registry. This step is the most time-consuming part of the Spring application startup process. This invention rewrites the `finishBeanFactoryInitialization` method in a custom lazy-loaded container, redefining the execution logic of this step. In the rewritten execution flow, the container only performs basic operations such as ConversionService initialization, embedded value resolver registration, LoadTimeWeaverAware initialization, and BeanFactory configuration freezing, and no longer executes the original BeanFactory's `preInstantiateSingletons()` batch pre-instantiation process. The main thread returns immediately after completing the `finishBeanFactoryInitialization` step without triggering any Bean instantiation, fundamentally eliminating the performance bottleneck of application cold starts.
[0016] S4: Execute until the refresh completion phase, intercept the container ready event publication, and the main thread returns quickly; After the finishBeanFactoryInitialization step is completed, the Spring container's refresh process enters the final step, finishRefresh. finishRefresh is the final step in the Spring container refresh process. In the finishRefresh step, the native Spring container performs cleanup operations such as clearing resource caches and publishing container ready events, and then the container declares that startup is complete. This invention overrides the `finishRefresh` method in a custom lazy-loaded container, redefining the execution logic of this step. In the rewritten execution flow, the container calls the parent class method to complete cleanup operations such as resource cache clearing. At the same time, the container overrides the `publishEvent` method, setting its execution logic to null. When the container's ready event is triggered during the execution of the parent class's `finishRefresh` method, the event publication is intercepted because the `publishEvent` method has been overridden with null logic. The main thread does not perform any event publication operations, but only completes resource cache clearing and other operations before returning immediately. After the above operations are completed, the finishRefresh step is finished, the refresh process of the Spring container is complete, the main thread completes the container startup, and the Spring application begins to provide services to the outside world.
[0017] S5: After the application starts, start a background asynchronous thread to load the Bean and publish the container ready event; After the main thread completes the refresh process, the Spring application starts up and begins to provide services. This step involves starting a background asynchronous thread to instantiate all beans in the background. S51: The background asynchronous thread executes the preInstantiateSingletons method of BeanFactory to complete the instantiation of all beans; The container starts a separate background asynchronous thread, in which the preInstantiateSingletons method of BeanFactory is executed. This method iterates through all non-lazy-loaded singleton Bean definitions in the Bean definition registry and executes instance creation, dependency injection, and complete initialization lifecycle callbacks one by one. S52: A background asynchronous thread publishes a container ready event; After the background asynchronous thread completes the instantiation of all business beans in BeanFactory's preInstantiateSingletons, the background asynchronous thread calls the parent class's publishEvent method to publish a container ready event, notifying all pre-registered event listeners to execute business warm-up, initialization and other processing logic. Since all business beans have been instantiated, dependency injected, and initialized by this time, all business components are fully ready when the listener is executed, and any warm-up or initialization operations of dependent business components can be safely performed; the publication of container ready events and the execution of listeners are both in background asynchronous threads, and the main thread is not blocked in any way.
[0018] This invention makes non-critical cleanup operations asynchronous by rewriting the container refresh completion logic, and loads the scheduled task component and the remaining business singleton component asynchronously through a background thread, thereby minimizing the main thread startup path and significantly shortening the application cold start time. This invention rewrites the finishRefresh and publishEvent lifecycle methods in a custom lazy-loaded container. It intercepts the main thread's full bean pre-instantiation logic and container ready event publishing logic by relying on the container lifecycle. The full bean instantiation and container ready event publishing are encapsulated as asynchronous tasks and delivered to the thread pool. The main thread returns immediately after submitting the task, without having to synchronously block and wait for the initialization operations of various non-core components. This simplifies the main thread startup chain to the greatest extent, significantly shortens the cold start time of Spring applications, and simultaneously reduces the peak JVM heap memory usage during the application startup phase.
[0019] The extreme cold start capability of this invention is perfectly suited to cloud-native architecture, significantly improving the efficiency of Serverless functions and Kubernetes Pod elastic scaling, and is widely adaptable to deployment scenarios that are sensitive to cold starts, such as microservices and edge computing. In business scenarios such as microservices, Kubernetes elastic scaling, and edge computing, application startup speed directly affects the deployment density of container clusters and the elastic scaling capability in cloud-native scenarios. This invention achieves on-demand loading and improves resource utilization efficiency by customizing lazy-loaded containers. It can significantly reduce startup time and effectively control memory peaks during startup, providing reliable technical support for cold start optimization of Serverless functions and rapid elastic scaling of Kubernetes Pods. It has good industrial application prospects and promotion value.
[0020] The present invention has been described in the above-described embodiments; however, these embodiments are merely examples for implementing the present invention. It must be noted that the disclosed embodiments do not limit the scope of the present invention. Conversely, any modifications and refinements made without departing from the spirit and scope of the present invention are within the scope of patent protection of the present invention.
Claims
1. A lazy loading method for Spring applications based on container lifecycle control, characterized in that: Includes the following steps: S1: Load a custom container factory via the SPI mechanism, create a custom lazy-loaded container, and set it as the default container context; S11: The startup core class loads the custom container factory via the SPI service loading mechanism; S12: The startup core class calls the creation method of the custom container factory to generate a custom lazy-loaded container instance; S13: The startup core class sets a custom lazy-loaded container instance as the application's default container context; S2: Execute the standard refresh process of the Spring container to complete the loading of Bean definitions and the instantiation and registration of BeanPostProcessor; After a custom lazy-loaded container instance is set as the default container context, the standard Spring container refresh process is executed, i.e., the refresh method is called. S3: Execute to the finishBeanFactoryInitialization step, skipping the full pre-instantiateSingletons pre-instantiation method of BeanFactory; S4: Execute until the refresh completion phase, intercept the container ready event publication, and the main thread returns quickly; S5: After the application starts, start a background asynchronous thread to load the Bean and publish the container ready event; S51: The background asynchronous thread executes the preInstantiateSingletons method of BeanFactory to complete the instantiation of all beans; S52: A background asynchronous thread publishes a container ready event.
2. The Spring application lazy loading method based on container lifecycle control as described in claim 1, characterized in that: The specific details of step S1 are as follows: S11: The startup core class loads the custom container factory via the SPI service loading mechanism; When a Spring application starts, its built-in startup core class scans the META-INF / spring.factories configuration file under the classpath through the Java standard SPI service loading mechanism. The META-INF / spring.factories configuration file is the SPI configuration file, and reads all SPI extension implementation classes registered in the SPI configuration file. The SPI configuration file pre-registers a custom container factory class. After the core class instantiates all SPI extension implementation classes, it selects the custom container factory instance generated by the custom container factory class from the generated SPI extension implementation instances and caches the custom container factory instance as the container factory instance used by the current Spring application. S12: The startup core class calls the creation method of the custom container factory to generate a custom lazy-loaded container instance; The startup core class calls the creation method corresponding to the cached container factory instance. After being overridden, the creation method corresponding to the container factory instance no longer returns the default native container of the Spring framework, but builds and returns a custom lazy-loaded container instance. The custom lazy loading container instance on which the custom lazy loading container instance is generated inherits from the Spring native annotation configuration container; S13: The startup core class sets a custom lazy-loaded container instance as the application's default container context; After the startup core class receives the returned custom lazy-loaded container instance, it sets the custom lazy-loaded container instance as the default container context used by the current Spring application.
3. The Spring application lazy loading method based on container lifecycle control as described in claim 1, characterized in that: The specific details of step S3 are as follows: In a custom lazy-loaded container, the finishBeanFactoryInitialization method is overridden to only perform ConversionService initialization, embedded value resolver registration, LoadTimeWeaverAware initialization, and BeanFactory configuration freezing operations, and no longer executes the original BeanFactory preInstantiateSingletons batch pre-instantiation process.
4. The Spring application lazy loading method based on container lifecycle control as described in claim 1, characterized in that: The specific details of step S4 are as follows: The `finishRefresh` method is overridden in a custom lazy-loading container beforehand. Within the overridden `finishRefresh` method, the parent class's `finishRefresh` method is called to clear the resource cache. The parent class is a Spring native annotation configuration container. The `publishEvent` event publishing method is also overridden, and the original event publishing execution code within the overridden `publishEvent` event publishing method is cleared, making the overridden `publishEvent` event publishing method an empty logic. After the finishBeanFactoryInitialization step is completed, the standard refresh process of the Spring container enters the finishRefresh step. In the finishRefresh step, the Spring native annotation configuration container performs resource cache cleanup and publishes container ready events. The Spring native annotation configuration container executes the execution logic, performs resource cache cleanup, publishes container ready events, and marks the container startup as complete. When the publish container ready event is triggered during the execution of the parent class finishRefresh method, the publishEvent method, which has been overridden and set to have empty logic, is executed. The publishEvent method does not perform any event publishing actions, thereby intercepting the event publishing operation in the main thread. The main thread does not perform any event publishing operations, but only completes the resource cache cleanup operation and returns immediately. After the finishRefresh step is completed, the standard refresh process of the Spring container ends, the main thread completes the container startup, and the Spring application provides services to the outside world.
5. The Spring application lazy loading method based on container lifecycle control as described in claim 1, characterized in that: The specific details of step S5 are as follows: S51: The background asynchronous thread executes the preInstantiateSingletons method of BeanFactory to complete the instantiation of all beans; The container starts a separate background asynchronous thread, in which the preInstantiateSingletons method of BeanFactory is executed. This method iterates through all non-lazy-loaded singleton Bean definitions in the Bean definition registry and executes instance creation, dependency injection, and complete initialization lifecycle callbacks one by one. S52: A background asynchronous thread publishes a container ready event; After the background asynchronous thread completes the instantiation of all business beans in BeanFactory's preInstantiateSingletons, the background asynchronous thread calls the parent class's publishEvent method to publish a container ready event, notifying all pre-registered event listeners to execute business warm-up and initialization processing logic. The parent class is the Spring native annotation configuration container that the custom lazy loading container inherits from.