Code execution method and apparatus, device, medium, product
Patent Information
- Application Number
- CN202610885541.X
- Authority / Receiving Office
- CN · China
- Patent Type
- Patents(China)
- Current Assignee / Owner
- Filing Date
- 2026-06-18
- Publication Date
- 2026-11-03
- Estimated Expiration
- 2046-06-18
AI Technical Summary
现有依赖注入方法通常与特定后端框架强耦合,依赖约定过多且性能开销较大,缺乏灵活性和可维护性。
By storing and managing dependency objects in the coroutine's local storage space, dependency injection is achieved by automatically retrieving dependency objects when the target code block is called, reducing dependence on specific frameworks, and reducing the use of reflection and proxy mechanisms through explicit method calls.
It achieves automatic passing and isolation of dependent objects, reduces performance overhead, provides a more flexible and intuitive dependency injection method, and improves code readability and maintainability.
Smart Images

Figure CN122450544B_ABST
Abstract
Description
Technical Field
[0001] This disclosure relates to, but is not limited to, the field of computer software technology, and in particular to a code execution method, apparatus, device, medium, and product. Background Technology
[0002] Dependency Injection (DI) is a software design pattern used to implement Inversion of Control (IoC). The core idea of DI is to transfer the management of dependencies between objects from within the objects themselves to an external container. Through constructors, setter methods, or interface injection, the container dynamically injects dependent objects into the code blocks that need them at runtime, thereby reducing code coupling and improving code testability and maintainability.
[0003] However, dependency injection methods in related technologies typically employ declarative dependency injection based on annotations or configuration files. This requires strong coupling with specific backend frameworks, involves too many dependency conventions, lacks flexibility, and incurs significant performance overhead. Summary of the Invention
[0004] In view of the above, the present disclosure provides at least one code execution method, apparatus, device, medium, and product.
[0005] The technical solution of this disclosure embodiment is implemented as follows: This disclosure provides a code execution method, including: Get the target code block to be invoked in the current coroutine, and at least one first dependency object that the target code block depends on; Store at least one primary dependency object in the local storage space of the current coroutine; Using the current coroutine, the target code block is invoked and executed in the local storage space, so as to retrieve at least one first dependent object from the local storage space during the invocation of the target code block.
[0006] This disclosure provides a code execution apparatus, including: The first acquisition module is used to acquire the target code block to be called by the current coroutine, and at least one first dependency object that the target code block depends on; The storage module is used to store at least one first dependent object in the local storage space of the current coroutine; The first calling module is used to call and execute the target code block in the local storage space using the current coroutine, so as to obtain at least one first dependent object from the local storage space during the calling of the target code block.
[0007] This disclosure provides a computer device including a memory and a processor. The memory stores a computer program that can run on the processor. When the processor executes the program, it implements some or all of the steps in the above-described method.
[0008] This disclosure provides a computer-readable storage medium having a computer program stored thereon, which, when executed by a processor, implements some or all of the steps in the above-described method.
[0009] This disclosure provides a computer program product, including a computer program or instructions, which, when executed by a processor, implement some or all of the steps in the above-described method.
[0010] In this embodiment, before invoking the target code block, the target code block and at least one first dependency object it depends on are obtained, and the at least one first dependency object is stored in the local storage space of the current coroutine. During the invocation phase of the target code block, the target code block is invoked and executed using the current coroutine in the local storage space, so that at least one first dependency object is obtained from the local storage space during the invocation of the target code block. Since each coroutine has its own independent local storage space, which can be accessed throughout the entire lifecycle of the coroutine, using the local storage space of the current coroutine as a storage container for at least one first dependency object depended on by the target code block to be invoked by the current coroutine allows each first dependency object to be automatically passed to the entire method call stack of the target code block during invocation within the coroutine. This allows the first dependency object to be obtained from the local storage space during the invocation of the target code block, achieving dependency object injection and complete isolation of dependencies between different coroutines. Thus, compared to declarative dependency injection methods based on annotations or configuration files in related technologies, the technical solution of this disclosure reduces the dependence of dependency injection on conventions and configurations, eliminates the need for strong coupling with specific backend frameworks, and provides a more intuitive and flexible dependency injection method. Furthermore, implementing dependency injection based on a coroutine local storage mechanism reduces the use of reflection and proxy mechanisms, lowering performance overhead during code execution.
[0011] It should be understood that the above general description and the following detailed description are merely exemplary and explanatory, and are not intended to limit the technical solutions of this disclosure. Attached Figure Description
[0012] The accompanying drawings, which are incorporated in and form part of this specification, illustrate embodiments consistent with this disclosure and, together with the specification, serve to illustrate the technical solutions of this disclosure.
[0013] Figure 1 A schematic diagram of the implementation flow of a code execution method provided in this embodiment of the disclosure. Figure 1 ; Figure 2 A schematic diagram of the implementation flow of a code execution method provided in this embodiment of the disclosure. Figure 2 ; Figure 3 This is a schematic diagram of a tree-like dependency injection structure provided in an embodiment of the present disclosure; Figure 4 This is a schematic diagram of the composition structure of a code execution device provided in an embodiment of the present disclosure; Figure 5 This is a schematic diagram of a hardware entity of a computer device in an embodiment of this disclosure. Detailed Implementation
[0014] To make the objectives, technical solutions, and advantages of this disclosure clearer, the technical solutions of this disclosure are further described in detail below with reference to the accompanying drawings and embodiments. The described embodiments should not be regarded as limitations on this disclosure. All other embodiments obtained by those skilled in the art without creative effort are within the scope of protection of this disclosure.
[0015] In the following description, references are made to “some embodiments,” which describe a subset of all possible embodiments. However, it is understood that “some embodiments” may be the same subset or different subsets of all possible embodiments and may be combined with each other without conflict.
[0016] The terms “first / second / third” are used merely to distinguish similar objects and do not represent a specific ordering of objects. It is understood that “first / second / third” may be interchanged in a specific order or sequence where permitted, so that the embodiments of this disclosure described herein can be implemented in an order other than that illustrated or described herein.
[0017] Unless otherwise defined, all technical and scientific terms used herein have the same meaning as commonly understood by one of ordinary skill in the art to which this disclosure pertains. The terminology used herein is for descriptive purposes only and is not intended to limit the scope of this disclosure.
[0018] This disclosure provides a code execution method, which can be executed by a computer device, including but not limited to at least one of a server, personal computer, smartphone, tablet computer, etc. Figure 1 A schematic diagram of the implementation flow of a code execution method provided in this embodiment of the disclosure. Figure 1 ,like Figure 1 As shown, the method includes the following steps S101 to S103: Step S101: Obtain the target code block to be called by the current coroutine, and at least one first dependency object that the target code block depends on.
[0019] Here, the current coroutine can be the root coroutine of the currently running application (i.e., the main coroutine when the application starts), or it can be a sub-coroutine of a coroutine in the application. This disclosure does not limit this. For example, the current coroutine can be a sub-coroutine in the application used to handle a single request (i.e., a request-level coroutine).
[0020] The target code block can include, but is not limited to, at least one of the functions, methods, etc., that the current coroutine is about to call. It is understood that the target code block may depend on at least one dependent object (denoted as the first dependent object) during the execution of the call; during dependency injection, the target code block becomes the scope of that at least one first dependent object.
[0021] Understandably, when the current coroutine is the root coroutine of the application, since the lifecycle of the root coroutine is bound to the application process, each first dependency object will not be recreated throughout the entire lifecycle of the application. That is, at least one first dependency object will become a singleton dependency object, thereby enabling dependency injection in the singleton pattern.
[0022] In some implementations, the computer device can parse the code to be executed by the current coroutine during the startup phase of the current coroutine to obtain the target code block to be invoked by the current coroutine and at least one first dependent object that the target code block depends on. For example, the target code block to be invoked by the current coroutine and at least one first dependent object that the target code block depends on can be received through an interface for registering dependent objects.
[0023] Step S102: Store at least one first dependent object in the local storage space of the current coroutine.
[0024] Here, the local storage space of the current coroutine refers to the storage space used independently by the current coroutine. For example, the local storage space of the current coroutine can be the coroutine local storage (CLS) of the current coroutine.
[0025] It is understandable that each coroutine has its own independent local storage space, and the scope of the coroutine's local storage space is the entire lifecycle of the coroutine, that is, the coroutine's local storage space can be accessed throughout the entire lifecycle of the coroutine.
[0026] In some implementations, the at least one first dependent object can be stored directly in the local storage space of the current coroutine.
[0027] In some implementations, each first dependent object corresponds to a first retrieval key for uniquely identifying the first dependent object. The system can retrieve the target code block to be invoked by the current coroutine, and at least one key-value pair of dependent objects corresponding to that target code block, and store the at least one key-value pair of dependent objects in the local storage space of the current coroutine. The key in the dependent object key-value pair is the first retrieval key corresponding to the first dependent object on which the target code block depends, and the value in the dependent object key-value pair is the first dependent object. The first retrieval key may include, but is not limited to, at least one of a type key representing the type of the first dependent object, a name key representing the name of the first dependent object, etc.
[0028] In some implementations, at least one first dependency object may be added to the coroutine context of the current coroutine, which is stored in the local storage space of the current coroutine.
[0029] Step S103: Using the current coroutine, call and execute the target code block in the local storage space, so as to obtain at least one first dependent object from the local storage space during the call of the target code block.
[0030] Here, the target code block is invoked and executed by the current coroutine. During the invocation of the target code block, the local storage space of the current coroutine is accessible. Therefore, at least one first dependency object that the target code block depends on can be obtained from the local storage space to complete dependency injection in the target code block. The current coroutine can then invoke and execute the target code block based on the injected at least one first dependency object.
[0031] In some implementations, at least one first dependency object that the target code block depends on may be stored in the coroutine context of the current coroutine, which is stored in the local storage space of the current coroutine. During the invocation phase of the target code block, the target code block may be invoked and executed using the current coroutine and based on the coroutine context.
[0032] In this embodiment, before invoking the target code block, the target code block and at least one first dependency object it depends on are obtained, and the at least one first dependency object is stored in the local storage space of the current coroutine. During the invocation phase of the target code block, the target code block is invoked and executed using the current coroutine in the local storage space, so that at least one first dependency object is obtained from the local storage space during the invocation of the target code block. Since each coroutine has its own independent local storage space, which can be accessed throughout the entire lifecycle of the coroutine, using the local storage space of the current coroutine as a storage container for at least one first dependency object depended on by the target code block to be invoked by the current coroutine allows each first dependency object to be automatically passed to the entire method call stack of the target code block during invocation within the coroutine. This allows the first dependency object to be obtained from the local storage space during the invocation of the target code block, achieving dependency object injection and complete isolation of dependencies between different coroutines. Therefore, compared to declarative dependency injection methods based on annotations or configuration files in related technologies, the technical solution of this disclosure reduces the dependency injection's dependence on conventions and configurations (e.g., it does not depend on specific annotation names, naming rules, and / or configuration file formats), and does not require strong coupling with a specific backend framework, providing a more intuitive and flexible dependency injection method. Furthermore, implementing dependency injection based on a coroutine local storage mechanism reduces the use of reflection and proxy mechanisms, lowering performance overhead during code execution.
[0033] In some implementations, steps S101 to S103 can be implemented using a scope injection method. This scope injection method can be called at any location in the current application to temporarily inject or override at least one first dependency object that the target code block to be called by the current coroutine depends on. The input parameters of the scope injection method may include the target code block to be called by the current coroutine and at least one first dependency object that the target code block depends on. After receiving the target code block to be called by the current coroutine and at least one first dependency object that the target code block depends on, the scope injection method can first store at least one first dependency object in the local storage space of the current coroutine. Then, using the current coroutine, the target code block is called and executed in the local storage space to retrieve at least one first dependency object from the local storage space during the call to the target code block. In this way, dependency injection and dependency retrieval can be achieved through explicit method calls without relying on reflection or proxy mechanisms. Developers can directly view and debug the implementation code in the scope injection method, and breakpoints can be set at the injection and retrieval points of dependency objects to directly observe the propagation process of dependency objects, making error information more intuitive and accurate. For example, this scope injection method can be a generic function. Furthermore, dependencies are visible in the code through explicit function calls, allowing developers to directly see the dependency injection and retrieval process without needing to consult configuration files or annotation definitions across different files, thus improving code readability and maintainability.
[0034] In some embodiments, storing at least one first dependent object in the local storage space of the current coroutine in step S102 may include the following steps S111 to S113: Step S111: Obtain the coroutine context of the current coroutine from the local storage space.
[0035] Step S112: Add at least one first dependency object to the coroutine context to obtain the updated coroutine context.
[0036] Step S113: Store the updated coroutine context in the local storage space.
[0037] Here, the coroutine context of the current coroutine includes the context information required for the current coroutine to run. During the lifecycle of the current coroutine, the coroutine context can be passed along with the coroutine's method call stack.
[0038] In some implementations, the coroutine context includes at least one context element, each of which is identified by a unique key. The first search key corresponding to the first dependent object and the first dependent object can be used as a context element, and this context element can be added to the coroutine context.
[0039] In some implementations, a target context element may be added to the coroutine context, and the at least one first dependency object may be added to the value of the target context element.
[0040] In some implementations, the data structure of the target context element's value can also be a set of key-value pairs, where the first retrieval key corresponding to the first dependent object and the first dependent object can be added as key-value pairs to the value of the target context element.
[0041] In the above embodiments, the coroutine context of the current coroutine is first obtained from the local storage space. Then, at least one first dependent object is added to the coroutine context to obtain the updated coroutine context. Finally, the updated coroutine context is stored in the local storage space. In this way, since the coroutine context can be passed along with the coroutine's method call stack during the current coroutine's lifecycle, by adding at least one first dependent object to the current coroutine's coroutine context, this first dependent object can be automatically passed to the entire method call stack of the target code block during the current coroutine's lifecycle. This supports scope management of the first dependent object based on the natural method call stack, further reducing strong coupling with specific backend frameworks and achieving more flexible scope control.
[0042] In some embodiments, adding at least one first dependent object to the coroutine context in step S112 to obtain the updated coroutine context may include the following steps S121 to S123: Step S121: Retrieve the coroutine context to obtain the first target context element used to store dependent objects.
[0043] Here, the first target context element can be a predefined context element used to store dependent objects.
[0044] In some implementations, the first target context element has a corresponding search key, which is used to uniquely identify the first target context element and can be used to search for the coroutine context. If a context element corresponding to the search key exists in the coroutine context, then that context element is used as the first target context element; if no context element corresponding to the search key exists in the coroutine context, then a first target context element is created based on the search key.
[0045] Step S122: Add at least one first dependency object to the first target context element to obtain the updated first target context element.
[0046] Here, at least one first dependent object is added to the first target context element in any suitable data structure, which is not limited in this embodiment of the disclosure.
[0047] In some implementations, the data structure of the value of the first target context element can be a set of key-value pairs, where the first retrieval key corresponding to the first dependent object and the first dependent object can be added as key-value pairs to the value of the first target context element.
[0048] In some implementations, the data structure of the value of the first target context element can be a list of objects, and the first dependent object can be added to the value of the first target context element.
[0049] In some implementations, at least one first dependency object can be added to the current first target context element to obtain an updated first target context element.
[0050] In some implementations, a new first target context element can be created based on the current first target context element, and at least one first dependency object can be added to the new first target context element to obtain an updated first target context element.
[0051] Step S123: Generate an updated coroutine context based on the updated first target context element.
[0052] In some implementations, the updated first target context element can be added to the current coroutine context to obtain the updated coroutine context.
[0053] In some implementations, a new coroutine context can be created based on the current coroutine context, and the updated first target context element can be added to the new coroutine context to obtain the updated coroutine context.
[0054] In the above embodiments, the coroutine context is retrieved to obtain a first target context element for storing dependent objects; at least one first dependent object is added to the first target context element to obtain an updated first target context element; and an updated coroutine context is generated based on the updated first target context element. In this way, by setting a specific first target context element for storing dependent objects in the coroutine context, the first dependent objects that a target code block depends on can be quickly and flexibly added to the coroutine context of the current coroutine, thereby automatically passing the first dependent objects that the target code block depends on to the entire method call stack of the target code block.
[0055] In some embodiments, the first target context element is used to store at least one first search key and a first dependency object corresponding to each first search key. Step S103, retrieving at least one first dependency object from local storage during the invocation of the target code block, may include the following steps S131 to S134: Step S131: During the process of calling the target code block, obtain the coroutine context of the current coroutine from the local storage space.
[0056] Step S132: Retrieve the coroutine context to obtain the first target context element.
[0057] Here, step S132 corresponds to step S121 above, and the implementation method of step S121 can be referred to during implementation.
[0058] Step S133: Determine the first target retrieval key corresponding to the first target dependency object to be injected.
[0059] Step S134: Using the first target retrieval key, retrieve the first target dependency object from the first target context element. The first target dependency object is used to call and execute the target code block.
[0060] Here, the first target dependency object is the first dependency object in the current target code block to be injected.
[0061] The first target retrieval key can be any suitable key used to uniquely identify the first target dependency object in the first target context element, and this embodiment of the present disclosure does not limit this. By using the first target retrieval key to search for each key-value pair in the first target context element, the first dependency object corresponding to the first target retrieval key can be obtained, and the first dependency object is used as the first target dependency object.
[0062] In some implementations, a globally unique key can be created for the first target dependency object based on its type information and / or name information; this key serves as the first target retrieval key for the first target dependency object. The type information of the first target dependency object can be automatically obtained at runtime or manually specified by the developer. The name information of the first target dependency object can be a developer-defined string or a system-generated string.
[0063] In some implementations, steps S131 to S134 can be implemented using a dependency retrieval method. This method can be invoked at any location in the current application to retrieve at least one first dependency object from local storage. The input parameters of this dependency retrieval method may include type information corresponding to the first target dependency object to be injected. After receiving the type information, the dependency retrieval method can retrieve the coroutine context of the current coroutine from local storage; search the coroutine context to obtain a first target context element; determine the first target retrieval key corresponding to the first target dependency object to be injected; and retrieve the first target dependency object from the first target context element using the first target retrieval key. The first target dependency object is used to call and execute the target code block. For example, this dependency retrieval method can be an inline generic function.
[0064] In the above embodiments, the first target context element is used to store at least one first search key and a first dependency object corresponding to each first search key. During the invocation of the target code block, the coroutine context of the current coroutine is obtained from the local storage space, the coroutine context is searched to obtain the first target context element, the first target search key corresponding to the first target dependency object to be injected is determined, and the first target dependency object is retrieved from the first target context element using the first target search key. The first target dependency object is used to call and execute the target code block. In this way, the first target dependency object to be injected can be quickly and flexibly retrieved from the first target context element using the first target search key during the invocation of the target code block.
[0065] In some embodiments, step S122, which involves adding at least one first dependent object to the first target context element to obtain an updated first target context element, may include the following steps S141 to S142: Step S141: Generate the first search key corresponding to the first dependent object based on the type information corresponding to the first dependent object.
[0066] Here, any suitable method can be used to generate a first retrieval key to uniquely identify the first dependent object based on the type information corresponding to the first dependent object. This disclosure does not limit this method.
[0067] In some implementations, the type information corresponding to the first dependent object can be automatically obtained at runtime, and the first search key corresponding to the first dependent object can be generated based on the type information. In this way, the first search key can be automatically generated for the first dependent object without the need for the developer to manually specify it.
[0068] Step S142: Add the first search key corresponding to the first dependent object and the first dependent object as a key-value pair to the first target context element to obtain the updated first target context element.
[0069] Here, a key-value pair can be generated by using the first search key as the key and the corresponding first dependency object as the value, and then the key-value pair can be added to the first target context element.
[0070] Determining the first target retrieval key corresponding to the first target dependency object to be injected in step S133 may include the following step S143: Step S143: Based on the type information corresponding to the first target dependency object to be injected, generate the first target retrieval key corresponding to the first target dependency object.
[0071] Here, the method of generating the corresponding first target retrieval key based on the type information corresponding to the first target dependent object can refer to the method of generating the corresponding first retrieval key based on the type information corresponding to the first dependent object in the aforementioned step S141.
[0072] In the above embodiments, a first retrieval key generated based on the type information corresponding to the first dependent object, and the first dependent object are added as a key-value pair to the first target context element in the coroutine context of the current coroutine. During the invocation phase of the target code block, a first target retrieval key corresponding to the first target dependent object is generated based on the type information corresponding to the first target dependent object to be injected, so as to retrieve the first target dependent object from the first target context element using the first target retrieval key. In this way, dependent objects can be bound to their corresponding types and stored in the coroutine context, thereby realizing type-based dependency injection and further improving the flexibility of dependency injection.
[0073] In some embodiments, generating the first retrieval key corresponding to the first dependent object based on the type information corresponding to the first dependent object in step S141 may include the following step S151: Step S151: Based on the type information and name information corresponding to the first dependent object, generate the first search key corresponding to the first dependent object.
[0074] In some implementations, the type information and name information corresponding to the first dependent object can be combined according to a predefined format to obtain the first search key for the first dependent object. For example, the type information and name information corresponding to the first dependent object can be concatenated as strings to obtain the first search key. Alternatively, the name information and type information corresponding to the first dependent object can be connected by a colon to obtain the first search key.
[0075] In some implementations, the type information and name information corresponding to the first dependent object can be concatenated into a string, and the concatenated string can be hashed to obtain the first search key corresponding to the first dependent object.
[0076] Step S143, which generates the first target retrieval key corresponding to the first target dependency object based on the type information of the first target dependency object to be injected, may include the following step S152: Step S152: Based on the type information and name information of the first target dependency object to be injected, generate the first target retrieval key corresponding to the first target dependency object.
[0077] Here, the method of generating the corresponding first target retrieval key based on the type information and name information of the first target dependent object can refer to the method of generating the corresponding first retrieval key based on the type information and name information of the first dependent object in the aforementioned step S151.
[0078] In the above embodiments, the first search key corresponding to the first dependent object is generated by comprehensively considering the type information and the name information of the first dependent object. In this way, when multiple first dependent objects have the same type information, they can be distinguished by name information, thereby supporting the coexistence of multiple first dependent objects of the same type and further improving the flexibility of dependency injection.
[0079] In some embodiments, the above code execution method may further include the following steps S161 to S163: Step S161: During the process of calling the target code block, obtain the type information corresponding to the second target dependency object to be injected, and the first creation function corresponding to the second target dependency object.
[0080] Here, the first creation function can be a predefined function used to create the second target dependency object. The second target dependency object is the second dependency object that is currently to be injected using the singleton pattern.
[0081] In some implementations, during the invocation of the target code block, the type information corresponding to the second target dependency object to be injected and the first creation function corresponding to the second target dependency object can be obtained by parsing the target code block.
[0082] Step S162: Generate a second target retrieval key based on the type information corresponding to the second target dependent object.
[0083] Here, the method of generating the corresponding second target retrieval key based on the type information corresponding to the second target dependency object can refer to the method of generating the corresponding first retrieval key based on the type information corresponding to the first dependency object in the aforementioned step S141.
[0084] Step S163: If there is no second dependent object corresponding to the second target retrieval key in the target mapping table, the first creation function is used to create the second target dependent object based on the type information corresponding to the second target dependent object, and the second target retrieval key and the second target dependent object are added to the target mapping table as key-value pairs; the target mapping table is shared across coroutines.
[0085] Here, the target mapping table can be shared across coroutines, meaning that all coroutines within the current application can access the target mapping table during the application's lifecycle. The target mapping table can be used to store at least one second dependency object and the corresponding search key for each second dependency object. It's understood that, since the second dependency objects are injected using a singleton pattern, each second dependency object will not be created repeatedly throughout the application's lifecycle; that is, for the same search key, only one globally unique second dependency object will be created.
[0086] In some implementations, the target mapping table can be thread-safe. For example, the target mapping table can be a thread-safe concurrent hash mapping table shared across coroutines.
[0087] In some implementations, the above code execution method may further include: step S164, if there is a second dependent object in the target mapping table that corresponds to the second target retrieval key, then the second dependent object is determined as the second target dependent object.
[0088] In some implementations, steps S161 to S164 can be implemented using a singleton injection method. This singleton injection method can be called at any location within the target code block where a singleton dependency object needs to be injected, to inject the second target dependency object in singleton mode at that location. The input parameters of this singleton injection method may include the type information corresponding to the second target dependency object to be injected and the first creation function corresponding to the second target dependency object. After receiving the type information and the first creation function of the second target dependency object, the singleton injection method can generate a corresponding second target retrieval key based on the received type information, and obtain a globally unique second target dependency object based on the second target retrieval key and the first creation function by calling the object retrieval method of a global singleton registry object. Internally, the singleton registry object maintains a thread-safe target mapping table, which stores singleton dependency objects shared across coroutines in the current application. For example, this target mapping table can be a concurrent hash mapping table. The singleton registry object also provides an object retrieval method to receive the second target retrieval key and the first creation function. If the second dependent object corresponding to the second target retrieval key already exists in the target mapping table, then the second dependent object in the target mapping table corresponding to the second target retrieval key is used as the second target dependent object, and this second target dependent object is returned directly; otherwise, the first creation function is called to create a new second dependent object as the second target dependent object, the second target retrieval key and the second target dependent object are stored as a key-value pair in the target mapping table, and the second target dependent object is returned. For example, the singleton injection method can be an inline generic function, and the object acquisition method of the singleton registry object can be a generic method.
[0089] In the above embodiments, during the invocation of the target code block, the type information corresponding to the second target dependency object to be injected and the first creation function corresponding to the second target dependency object are obtained; based on the type information corresponding to the second target dependency object, a second target retrieval key is generated; if there is no second dependency object corresponding to the second target retrieval key in the target mapping table, the second target dependency object is created using the first creation function based on the type information corresponding to the second target dependency object, and the second target retrieval key and the second target dependency object are added to the target mapping table as key-value pairs. Thus, since the target mapping table is shared across coroutines, each second dependency object in the target mapping table will not be repeatedly created throughout the entire lifecycle of the application, meaning each second dependency object is a singleton dependency object. Therefore, singleton dependency injection can be flexibly implemented at any suitable location in the target code block based on the type information corresponding to the second target dependency object to be injected and the first creation function corresponding to the second target dependency object, making it suitable for scenarios where singleton dependency objects need to be shared among multiple coroutines.
[0090] In some embodiments, the target code block includes a target function. Step S103 above, which involves using the current coroutine to call and execute the target code block in local storage space to obtain at least one first dependent object from local storage space during the call to the target code block, may include the following step S171: Step S171: Invoke the auxiliary call function corresponding to the target function; the auxiliary call function is used to call the dependency retrieval method, obtain at least one first dependency object from the local storage space, and use the current coroutine to call and execute the target function with at least one first dependency object as a function parameter.
[0091] In some implementations, the auxiliary calling function can be manually written by the developer based on the type and / or name information of the target function and the first dependent object on which the target function depends.
[0092] In some implementations, the auxiliary calling function can be automatically generated by annotation processors or compiler plugins based on the type and / or name information of the target function and its first dependent object. For example, the type information of the first dependent object can be generated using a compiler-preset type inference mechanism (such as Kotlin's reified mechanism). This allows for type matching checks during code compilation, reducing runtime type conversion errors and providing better type safety.
[0093] In the above embodiments, an auxiliary function corresponding to the target function is invoked. This auxiliary function calls a dependency retrieval method to obtain at least one first dependency object from local storage. Using the current coroutine, it calls and executes the target function with the at least one first dependency object as a function parameter. This allows dependency retrieval to be achieved through explicit method calls, without relying on reflection or proxy mechanisms. Developers can directly view and debug the implementation code in the auxiliary function, and breakpoints can be set at the dependency object retrieval points to directly observe the dependency object retrieval process, making error messages more intuitive and accurate.
[0094] In some embodiments, the above code execution method may further include the following steps S181 to S183: Step S181: Remove at least one target parameter with the first injection annotation from the first parameter list of the objective function to obtain the second parameter list; the target parameter represents the first dependent object on which the objective function depends.
[0095] Here, the target function may have a first function signature and a first function body. The first function signature includes the first function name and the first parameter list of the target function. The first parameter list includes at least one function parameter of the target function. For at least one first dependent object that the target function depends on, the first dependent object can be injected into the target function as a parameter, and the function parameters representing the first dependent object are marked with a set first injection annotation. Therefore, the function parameters in the first parameter list with the first injection annotation are the target parameters representing the first dependent objects that the target function depends on. The first function body is used to define the specific functionality implemented by the target function.
[0096] In some implementations, the target parameters may include, but are not limited to, the type information and / or name information of the first dependent object on which the target function depends.
[0097] Step S182: Determine the second function name based on the first function name of the objective function and the preset identification information.
[0098] Here, a preset identifier can be added to the first function name to obtain the second function name of the auxiliary calling function. This identifier can be any suitable identifier that is preset and used to identify the auxiliary calling function.
[0099] For example, a preset suffix can be added to the first function name to obtain a second function name for the auxiliary function call.
[0100] Step S183: Based on the second parameter list, the second function name, and at least one target parameter, generate an auxiliary calling function; the function body of the auxiliary calling function includes a first code segment and a second code segment; the first code segment is used to call the dependency retrieval method based on the target parameter to obtain the first dependency object corresponding to the target parameter from the local storage space; the second code segment is used to use the current coroutine to call and execute the target function with at least one first dependency object as a function parameter.
[0101] Here, the second function name is the function name of the auxiliary calling function, and the second parameter list is the parameter list of the auxiliary calling function. Therefore, based on the second parameter list and the second function name, the second function signature of the auxiliary calling function can be obtained.
[0102] The first code segment may include any suitable code for invoking the dependency retrieval method based on the target parameter, and this disclosure does not limit this. The dependency retrieval method is used to retrieve a first dependency object corresponding to the target parameter from local storage space. The target parameter can be used as the input parameter of the dependency retrieval method, and the return result of the dependency retrieval method can be used as the first dependency object corresponding to the target parameter.
[0103] The second code segment may include any suitable code for utilizing the current coroutine to call and execute a target function, passing at least one first dependency object as a function parameter; this disclosure does not limit this. Specifically, after obtaining the first dependency objects returned by the dependency retrieval method, each first dependency object and each function parameter in the second parameter list can be passed to the target function to call and execute the target function.
[0104] In some implementations, if the target function to be called at the current call point is detected to have a second injection annotation, an auxiliary calling function corresponding to the target function can be obtained, the target function at the current call point can be replaced with the auxiliary calling function, and then the auxiliary calling function can be called. The second injection annotation can be any pre-defined, suitable annotation used to identify the function to be called at the current call point as the target function to be injected into dependency.
[0105] In some implementations, steps S181 to S183 can be implemented using a code generation method, which can be executed at the call points of the functions to be called in the application by an annotation processor or compiler plugin. Developers can mark the function to be injected by adding a second injection annotation and a first injection annotation to the target parameters to be injected within that function. The code generation method first identifies whether the function at the current call point is the target function to be injected. For example, it can identify whether the function at the current call point has a second injection annotation and / or whether the function parameters at the current call point include target parameters with the first injection annotation. If the function at the current call point is the target function to be injected, steps S181 to S183 are executed to generate an auxiliary call function corresponding to the target function, and the target function at the current call point is replaced with the auxiliary call function. Then, the auxiliary call function is called.
[0106] In the above embodiments, at least one target parameter with a first injection annotation is removed from the first parameter list of the target function to obtain a second parameter list; the target parameter represents the first dependency object on which the target function depends; a second function name is determined based on the first function name of the target function and preset identification information; an auxiliary calling function is generated based on the second parameter list, the second function name, and at least one target parameter. The function body of the auxiliary calling function includes a first code segment and a second code segment; the first code segment is used to call a dependency retrieval method based on the target parameter to obtain the first dependency object corresponding to the target parameter from local storage space; the second code segment is used to use the current coroutine, taking at least one first dependency object as a function parameter, to call and execute the target function. In this way, during the calling process of the target function to be injected with parameters, an auxiliary calling function corresponding to the target function can be automatically generated, and dependency injection of the target function's parameters can be automatically completed by calling the auxiliary calling function. Furthermore, the code in the generated auxiliary calling function is a direct type-safe call, requiring no large amount of reflection operations, resulting in high performance and significantly reducing the runtime overhead of the application.
[0107] In some embodiments, the above code execution method may further include the following steps S191 to S193: Step S191: During the invocation of the target code block, obtain the type information corresponding to the target delayed dependency wrapper class and the second creation function corresponding to the third target dependency object to be delayed injection.
[0108] Here, the target lazy dependency wrapper class can be a predefined class for lazy injection of dependency objects. This wrapper class can internally define a dependency object retrieval method, which can be used to retrieve a third target dependency object. This third target dependency object is the dependency object of the target code block to be lazy-injected.
[0109] The second creation function can be a predefined function used to create a third target dependency object.
[0110] In some implementations, during the invocation of the target code block, the type information of the target delayed dependency wrapper class corresponding to the third target dependency object to be delayed injection, as well as the second creation function corresponding to the third target dependency object, can be obtained by parsing the target code block.
[0111] Step S192: Based on the type information corresponding to the target delayed dependency wrapper class, obtain the target delayed dependency wrapper object corresponding to the target delayed dependency wrapper class from the local storage space; the target delayed dependency wrapper object has a dependency object acquisition method, which is used to create a third target dependency object using the second creation function.
[0112] Here, the local storage space of the current coroutine can also be used to store at least one deferred dependency wrapper object. Based on the type information corresponding to the target deferred dependency wrapper class, a deferred dependency wrapper object matching the type information can be retrieved from the local storage space, and this deferred dependency wrapper object can be used as the target deferred dependency wrapper object corresponding to the target deferred dependency wrapper class.
[0113] In some implementations, if a delayed dependency wrapper object that matches the type information of the target delayed dependency wrapper class exists in the local storage space, the delayed dependency wrapper object can be used as the target delayed dependency wrapper object corresponding to the target delayed dependency wrapper class.
[0114] In some implementations, if there is no delayed dependency wrapper object in the local storage space that matches the type information of the target delayed dependency wrapper class, a target delayed dependency wrapper object corresponding to the target delayed dependency wrapper class can be created based on the type information corresponding to the target delayed dependency wrapper class.
[0115] In some implementations, steps S191 to S192 can be implemented using a delayed injection method. This delayed injection method can be called at any location within the target code block where delayed injection of dependent objects is required, to inject a third target dependent object at that location using delayed injection. The input parameters of this delayed injection method may include type information corresponding to the target delayed dependency wrapper class and a second creation function corresponding to the third target dependent object to be delayed injected. After receiving the type information and the second creation function, the delayed injection method can retrieve the target delayed dependency wrapper object corresponding to the target delayed dependency wrapper class from local storage based on the received type information and return the target delayed dependency wrapper object. For example, this delayed injection method can be an inline generic function.
[0116] Step S193: At the call point corresponding to the third target dependency object, call the dependency object acquisition method of the target delayed dependency wrapper object to obtain the third target dependency object.
[0117] Here, the invocation point corresponding to the third target dependency object refers to the location within the target code block where the third target dependency object needs to be used during application runtime. At this invocation point, the third target dependency object can be obtained by calling the dependency object retrieval method of the target lazy dependency wrapper object.
[0118] In the above embodiments, during the invocation of the target code block, the type information corresponding to the target delayed dependency wrapper class and the second creation function corresponding to the third target dependency object to be delayed-injected are obtained. Based on the type information corresponding to the target delayed dependency wrapper class, the target delayed dependency wrapper object corresponding to the target delayed dependency wrapper class is obtained from the local storage space. This target delayed dependency wrapper object has a dependency object retrieval method, which is used to create the third target dependency object using the second creation function. At the call point corresponding to the third target dependency object, the dependency object retrieval method of the target delayed dependency wrapper object is called to retrieve the third target dependency object. In this way, delayed injection of dependency objects can be achieved through explicit method calls, without relying on reflection or proxy mechanisms, which can further reduce the performance overhead during code execution. Furthermore, developers can directly view and debug the implementation code of the delayed injection, and breakpoints can be set at the delayed injection and retrieval points of dependency objects, facilitating code debugging.
[0119] In some embodiments, the target delayed dependency wrapper object also has a target cache field. The method for obtaining the dependency object of the target delayed dependency wrapper object is used at least in the following steps S1101 to S1102: Step S1101: If the target cache field is empty, create a third target dependency object using the second creation function, store the third target dependency object in the target cache field, and return the third target dependency object.
[0120] Step S1102: If the target cache field is not empty, retrieve and return the third target dependency object from the target cache field.
[0121] Here, the target lazy dependency wrapper object can maintain a target cache field, which can be used to store the third target dependency object created by the second creation function.
[0122] The implementation method of the target cache field can be set according to the actual situation, and this disclosure does not limit it. For example, the target cache field can be implemented by a list, queue, or set.
[0123] In the above embodiments, when the target cache field is empty, a third target dependency object is created using the second creation function, stored in the target cache field, and returned. When the target cache field is not empty, the third target dependency object is retrieved from and returned. This allows the third target dependency object to be stored in the target cache field after creation, so that when the dependency object retrieval method is called again, the third target dependency object is not recreated; the already created object is directly returned. This enables singleton injection of the third target dependency object and improves the efficiency of delayed injection, thereby improving code execution performance.
[0124] In some embodiments, obtaining the target delayed dependency wrapper object corresponding to the target delayed dependency wrapper class from the local storage space based on the type information corresponding to the target delayed dependency wrapper class in step S192 above may include the following steps S1111 to S1114: Step S1111: Obtain the coroutine context of the current coroutine from the local storage space.
[0125] Step S1112: Retrieve the coroutine context to obtain the second target context element; the second target context element is used to store at least one second search key and the lazy dependency wrapper object corresponding to each second search key.
[0126] Here, the second target context element may be the same as or different from the first target context element, and this disclosure does not limit this.
[0127] Step S1113: Based on the type information corresponding to the target delayed dependency wrapper class, determine the third target retrieval key corresponding to the target delayed dependency wrapper object.
[0128] Step S1114: Using the third target retrieval key, retrieve the target delayed dependency wrapper object from the second target context element.
[0129] Here, the third target retrieval key can be any suitable key used to uniquely identify the delayed dependency wrapper object in the second target context element, and this embodiment of the disclosure does not limit this. By using the third target retrieval key to search for each key-value pair in the second target context element, the delayed dependency wrapper object corresponding to the third target retrieval key can be obtained, and this delayed dependency wrapper object is used as the target delayed dependency wrapper object.
[0130] In some implementations, a globally unique key, i.e., the third target retrieval key of the target delayed dependency wrapper object, can be generated based on the type information corresponding to the target delayed dependency wrapper class and / or the name information corresponding to the target delayed dependency wrapper object. The type information corresponding to the target delayed dependency wrapper class can be automatically obtained at runtime or manually specified by the developer. The name information corresponding to the target delayed dependency wrapper object can be a developer-defined string or a system-generated string.
[0131] In the above embodiments, the coroutine context of the current coroutine is obtained from the local storage space; the coroutine context is searched to obtain a second target context element; the second target context element is used to store at least one second search key and a delayed dependency wrapper object corresponding to each second search key; based on the type information corresponding to the target delayed dependency wrapper class, a third target search key corresponding to the target delayed dependency wrapper object is determined; using the third target search key, the target delayed dependency wrapper object is retrieved from the second target context element. In this way, the type information corresponding to the target delayed dependency wrapper class can be used to quickly and flexibly retrieve the target delayed dependency wrapper object to be delayed-injected from the first target context element.
[0132] In some embodiments, the above code execution method may further include the following step S1121: Step S1121: In response to the completion of the execution of the target code block, at least one first dependency object is removed from the local storage space.
[0133] Understandably, removing the first dependent object from local storage will prevent it from being retrieved there. In other words, once the target code block completes execution, the first dependent object it depends on will become invalid. This allows for control over the scope of dependent objects based on the natural call boundaries of the target code block.
[0134] In some implementations, the target code block may call a next-level sub-code block. During the call to the next-level sub-code block, the next-level sub-code block to be called by the current coroutine and at least one fourth dependent object that the next-level sub-code block depends on can be obtained. At least one fourth dependent object is stored in the local storage space of the current coroutine. Using the current coroutine, the next-level sub-code block is called and executed in the local storage space, so as to obtain at least one fourth dependent object from the local storage space during the call to the next-level sub-code block. In response to the completion of the execution of the next-level sub-code block, at least one fourth dependent object is removed from the local storage space.
[0135] In this way, on the one hand, since at least one first dependency object that the target code block depends on is not removed from the local storage space during the call to the next-level sub-code block, this first dependency object can be shared during the call and execution of the next-level sub-code block. On the other hand, since at least one fourth dependency object that the next-level sub-code block depends on is stored in the local storage space of the current coroutine when the next-level sub-code block is called, and is removed from the local storage space after the execution of the next-level sub-code block, the scope of this at least one fourth dependency object is the next-level sub-code block. That is, the dependency objects injected during the call to the next-level sub-code block of the target code block are isolated from other code in the target code block except for the next-level sub-code block. In this way, based on the entire method call stack of the target code block, the dependency objects of code blocks at different levels can be naturally isolated and shared, thereby achieving fine-grained scope dependency injection.
[0136] The following describes the application of the embodiments of this disclosure in a real-world scenario, demonstrating how dependency injection can be implemented based on coroutines.
[0137] Dependency injection frameworks in related technologies typically employ declarative dependency injection methods based on annotations or configuration files.
[0138] Taking the Spring framework as an example, the implementation process of its technical solution is as follows: 1) Dependency Declaration: Developers declare dependencies between classes using annotations (such as "@Autowired", "@Inject", "@Component", etc.) or Extensible Markup Language (XML) configuration files. For example, adding the "@Autowired" annotation to a class's field, constructor, or setter method will allow the framework to automatically identify and inject the corresponding dependent objects.
[0139] 2) Container initialization: When the application starts, the framework scans the specified package path, identifies all classes with specific annotations (such as "@Component", "@Service", "@Repository", etc.), and registers these classes into the IoC container.
[0140] 3) Entity Class (Bean) Creation and Injection: The container creates Bean instances in a specific order based on the dependency graph. For Beans with Singleton scope, the container creates and caches them during initialization; for Beans with Prototype scope, a new instance is created on each request. The container completes dependency injection by calling the constructor or setter method through reflection.
[0141] 4) Scope Management: The framework provides predefined scopes, such as Singleton, Prototype, Request, and Session. Developers specify the scope of a bean using the "@Scope" annotation, and the container manages the bean's lifecycle according to the scope rules.
[0142] 5) Handling circular dependencies: For circular dependencies, frameworks usually use a three-level caching mechanism or delayed injection of proxy objects to solve the problem.
[0143] The dependency injection methods in the aforementioned related technologies have the following problems: 1) Excessive Dependency Conventions: Existing frameworks require developers to follow numerous naming, annotation, and configuration conventions. For example, the Spring framework requires the use of specific annotation names (such as "@Component", "@Service", etc.), bean naming must follow camelCase, and configuration files must follow specific language or property formats. These conventions increase the learning curve, and if these conventions are violated, the framework may fail to correctly identify and inject dependencies.
[0144] 2) Debugging difficulties: Because dependency injection occurs internally within the framework and is implemented through reflection and proxy mechanisms, developers find it difficult to directly observe and trace the execution flow of dependency injection. When problems such as dependency injection failure, circular dependencies, or scope mismatches occur, the error messages are often not intuitive enough, requiring in-depth analysis of the framework's source code to locate the problem. Furthermore, the framework's initialization process is implicit, making it difficult for developers to set breakpoints for debugging during the injection process.
[0145] 3) Inflexible Scope: Existing frameworks provide predefined, fixed scopes that are tightly bound to specific backend frameworks (such as web frameworks), such as Singleton, Prototype, Request, and Session. These scopes are human-defined abstract concepts that developers need to explicitly specify through annotations (such as "@Scope("request")") for the framework to recognize and manage them. Existing frameworks do not support scopes based on the natural method call stack, meaning they cannot automatically identify the context boundaries of method calls and automatically determine the scope of dependent objects based on the call stack. For example, in the Spring framework, the Request scope must be bound to the lifecycle of a Hypertext Transfer Protocol (HTTP) request, and the Session scope must be bound to an HTTP session. These scopes are strongly coupled to specific concepts of web frameworks and cannot be applied to non-web environments or custom call contexts. Developers cannot achieve fine-grained scope control based on natural call boundaries, such as "for the same request, binding a singleton dependency object within one method call chain, and creating a new dependency object in another method call chain," nor can they dynamically define custom scopes independent of the framework based on business logic.
[0146] 4) Difficulty in adapting to temporary injection requirements: Existing frameworks perform dependency injection at object creation time, which is a one-time, static process. For scenarios requiring dynamic, temporary changes to dependencies, such as lazy initialization, conditional injection, and runtime dependency replacement, existing frameworks lack sufficient support. Although some frameworks provide the "@Lazy" annotation, its implementation mechanism is still based on proxies, failing to truly achieve on-demand delayed creation and lacking flexible runtime control over the delay strategy.
[0147] 5) Insufficient thread / coroutine context isolation: Existing frameworks primarily manage scope based on threads or HTTP requests, offering insufficient support for context isolation in modern asynchronous programming models (such as coroutines and asynchronous tasks). In a coroutine environment, different coroutines may need to share certain dependencies while isolating others; existing frameworks struggle to precisely control such fine-grained scope boundaries.
[0148] 6) Significant performance overhead: Existing frameworks heavily rely on reflection to create objects and inject dependencies, which incurs a significant performance overhead compared to direct calls. Furthermore, to support Aspect-Oriented Programming (AOP) and proxy functionality, frameworks often need to create proxy objects, further increasing memory and performance overhead.
[0149] 7) Separation of configuration and code leads to poor readability: Although XML configuration or annotation configuration provides declarative dependency management, the dependencies are scattered across multiple configuration files and code files. Developers need to look across files to understand the complete dependency graph, which reduces the readability and maintainability of the code.
[0150] In view of the technical problems existing in the dependency injection frameworks of the above-mentioned related technologies, this disclosure provides a code execution method for implementing coroutine-based dependency injection, which can at least solve the following technical problems: 1) Reduce reliance on conventions and configurations, and provide a more intuitive and flexible dependency injection method; 2) Improve the debuggability of the dependency injection process, making the execution flow of dependency injection explicit and traceable; 3) Supports scope management based on the natural method call stack, breaking free from strong coupling with specific backend frameworks and achieving flexible scope control; 4) Supports dynamic and temporary dependency injection requirements, such as delayed initialization and conditional injection scenarios; 5) Provides precise control over coroutine local storage, enabling fine-grained dependency isolation and sharing; 6) Reduce performance overhead by minimizing the use of reflection and proxy mechanisms; 7) Improve code readability by making dependencies explicitly visible in the code.
[0151] The core idea of the code execution method provided in this disclosure is to utilize the coroutine local storage mechanism to pass and manage dependent objects throughout the backend process. Dependencies are identified and retrieved using types or strings as keys, enabling type injection, named injection, parameter injection, singleton injection, and lazy injection. For parameter injection, code generation technology can automatically generate methods for reading or creating corresponding dependent objects from the coroutine local storage.
[0152] This disclosure provides a code execution method that includes the following core mechanisms and processes: (a) Coroutine Local Storage Mechanism This embodiment utilizes a coroutine local storage mechanism as a storage container for dependent objects. Each coroutine has its own independent local storage space, which can store custom data elements. Dependent objects are stored as data elements in the coroutine's local storage and are automatically passed to the entire method call stack as the coroutine executes.
[0153] (ii) Dependency Registration and Binding Provides a dependency registration interface, allowing developers to bind dependency objects to the coroutine's local storage. Binding methods include: 1) Type Binding: Binds dependent objects to a type key, using the type key as a unique identifier for retrieval. Globally unique type keys can be automatically generated using type inference mechanisms (such as Kotlin's reified mechanism), eliminating the need for developers to manually specify key names. The type key can be generated based on the type information of the dependent object.
[0154] 2) Name Binding: Binds dependent objects to string keys, supporting the differentiation and injection of multiple instances of the same type through different names. The string key is determined by type and name information; in the aforementioned embodiments, both the first and second search keys can be type keys or string keys.
[0155] 3) Singleton Binding: For dependency objects that need to maintain a unique instance throughout the entire application lifecycle, a singleton binding mechanism is provided. By registering dependencies through type binding on the root coroutine, the traditional singleton dependency pattern can be implemented, ensuring that dependency objects corresponding to the same key are unique throughout the entire process.
[0156] (III) Dependency Injection and Retrieval Provides dependency injection and retrieval interfaces, including: 1) Scope Injection Method: This method receives a coroutine local storage modification function (corresponding to the target code block in the aforementioned embodiment). During the execution of this function, the specified dependent objects are injected into the coroutine local storage, and are automatically cleaned up after the function finishes execution. This method supports generic type parameters (Reified Type Parameter), which automatically determines the type key and / or string key of the dependent objects using type inference.
[0157] 2) Dependency Retrieval Methods: Provides methods for retrieving dependency objects from the current coroutine's local storage, supporting retrieval by type key or string key. If a dependency object does not exist, it can be automatically created based on a predefined first creation function.
[0158] (iv) Parameter injection code generation For scenarios requiring dependency objects to be injected as function parameters, a code generation method is provided. Developers specify the target parameters to be injected via annotations or configuration, and the code generation method will: 1) Analyze the function signature of the target function to identify the types and names of the parameters to be injected; 2) Generate an auxiliary calling function that reads or creates the corresponding dependency object from the current coroutine's coroutine local storage; 3) Insert the calling code of the generated auxiliary calling function into the calling point of the target function to achieve automatic parameter injection.
[0159] The code generation method generates explicit, debuggable plain code that does not rely on reflection or proxy mechanisms. Developers can directly view and debug the generated code.
[0160] (v) Scope Management In this embodiment of the disclosure, the scope management of dependent objects is implemented based on the natural execution boundary of coroutines: 1) Coroutine scope: Each coroutine has an independent scope of dependent objects. Dependencies injected through the scope injection method when the coroutine starts are available throughout the entire execution of the coroutine (including all child coroutines and method call processes of the coroutine).
[0161] 2) Method call stack scope: Dependency objects are passed naturally along the method call stack without explicit configuration. A dependency object injected in a method can be accessed in all methods in the direct or indirect call chain of that method.
[0162] 3) Dynamic scope switching: Developers can temporarily inject new dependency objects or overwrite existing dependency objects at any point using the scope injection method, achieving dynamic scope switching. Dependency objects are automatically passed along the method call stack through coroutine local storage, without the need for explicit configuration.
[0163] (vi) Dependency lifecycle management This disclosure employs a unified dependency lifecycle management mechanism, where the lifecycle of all dependent objects is bound to a coroutine. The lifecycle of a dependent object is determined by the coroutine that registered that object. 1) Coroutine Lifecycle Binding: The lifecycle of all dependent objects registered through scope injection is bound to the coroutine that registered the dependent object. When a coroutine finishes execution, the dependent objects in the coroutine's local storage are automatically cleaned up.
[0164] 2) Singleton Dependency: By registering dependencies on the root coroutine, the traditional singleton dependency pattern can be implemented. Since the lifecycle of the root coroutine is bound to the entire application process, the dependency object registered on the root coroutine remains a unique instance throughout the entire application runtime, equivalent to the singleton scope in traditional frameworks.
[0165] 3) Request-level dependencies: By registering dependencies on request handling methods, the traditional request-level dependency pattern can be implemented. Since the lifecycle of a request handling coroutine is bound to a single request, the dependent objects registered on the request handling coroutine remain unique instances during the invocation and execution of the request handling method, and are automatically cleaned up after the request is processed, which is equivalent to the request scope in traditional frameworks.
[0166] 4) Nested scope dependency: Dependency objects registered by a method can be injected at any position in the method call stack through scope injection. Their lifecycle is bound to the scope of that method call stack. When the scoped code block finishes execution, the dependency objects registered within that scope are automatically cleaned up, but this does not affect the dependencies of the outer scope.
[0167] The following uses the Kotlin language as an example to illustrate the implementation of the code execution method provided in this disclosure, including dependency injection implementation based on Kotlin coroutine context and dependency injection implementation supporting lazy initialization.
[0168] (a) Dependency Injection Based on Kotlin Coroutine Context This disclosure utilizes Kotlin's CoroutineContext mechanism to implement dependency injection, achieving the following functionality: 1) Define the dependent storage context element First, a custom dependency context element (corresponding to the first or second target context element in the aforementioned embodiments) is defined to store dependency objects. This dependency context element internally maintains a key-value pair mapping table, where the keys can be type keys or string keys, and the values are the corresponding dependency object instances. This dependency context element inherits from the abstract base class of the coroutine context element and contains a companion object as a key, used to identify the dependency context element within the coroutine context. This dependency context element provides three core methods: a retrieve method, used to retrieve the dependency object from the internal key-value pair mapping table based on the key and return the specified type; a place method, used to store key-value pairs into the key-value pair mapping table; and a remove method, used to delete the specified key-value pair from the key-value pair mapping table.
[0169] 2) Implement type key generation mechanism By leveraging Kotlin's reified mechanism to obtain the type parameters (corresponding to the type information in the previous example) and inline functions of the dependency objects to be injected, automatic key generation based on type is achieved. An inline generic function can be defined that receives the type parameters obtained through the reified mechanism and creates a type key object using the class object of those type parameters. A globally unique type key object can be generated for each type of the dependency object to be injected. This key object encapsulates the class information of the corresponding type and can be used as a key in the coroutine's local storage.
[0170] 3) Implement the scope injection method This scope injection method is a generic function that accepts a variable number of dependency object key-value pair bindings and a function code block (corresponding to the target code block in the previous example) as parameters. The method execution flow is as follows: First, it obtains the current coroutine's coroutine context, retrieves the dependency context element from the coroutine context, and creates a new empty dependency context element if it does not exist. Then, it creates a new dependency context element based on the current dependency context element and adds the newly passed key-value pair bindings to the new dependency context element. Next, it adds the new dependency context element to the current coroutine context, resulting in a new coroutine context. Finally, it executes the passed function code block using the new coroutine context. After the function code block completes execution, the new coroutine context automatically becomes invalid, achieving automatic cleanup of dependency objects.
[0171] 4) Implement dependency retrieval methods An inline generic function is provided as a dependency retrieval method. This method supports type parameters obtained based on the reified mechanism and automatically determines the type parameters of the dependency objects to be retrieved using type inference. The execution flow of this dependency retrieval method is as follows: First, the coroutine context of the current coroutine is obtained. The dependency context element is retrieved from the coroutine context. If the dependency context element does not exist, an exception is thrown. Then, the corresponding type key is generated based on the type parameters obtained from the reified mechanism. Next, the corresponding dependency object is retrieved from the dependency context element based on the type key. If the retrieval is successful, the dependency object is returned; otherwise, an exception is thrown. The exception message includes type information for debugging purposes.
[0172] 5) Implement named injection An inline generic function is provided as a named injection method, supporting named injection via string keys and allowing multiple dependent object instances of the same type to coexist. This named injection method accepts a string name parameter and a type parameter obtained based on `reified`. The execution flow of this named injection method is as follows: First, the coroutine context of the current coroutine is obtained. The dependent context element is retrieved from the coroutine context; if it does not exist, an exception is thrown. Then, a composite key is generated based on the type and name information, in the format of name followed by a colon and then the type information. Next, the corresponding dependent object is retrieved from the dependent context element based on the composite key. If the retrieval is successful, the dependent object is returned; otherwise, an exception is thrown, with the exception message including type and name information for debugging purposes.
[0173] 6) Implement singleton binding The singleton pattern is implemented by binding a unified lifecycle to a coroutine. This approach is suitable for scenarios where dependent objects need to be shared among multiple coroutines.
[0174] In some implementations, dependency objects can be registered on the root coroutine. Since the lifecycle of the root coroutine is bound to the entire application process, the dependency object naturally becomes a singleton dependency object.
[0175] In some implementations, an optional singleton registry object may be provided. This singleton registry object internally maintains a thread-safe concurrent hash map to store singleton dependency objects shared across coroutines. The singleton registry object provides a generic method as an object retrieval method. This method receives the second target retrieval key corresponding to the second target dependency object to be injected, and the first creation function corresponding to the second target dependency object. If the second dependency object corresponding to the second target retrieval key already exists, it returns directly; otherwise, it calls the first creation function to create a new second dependency object as the second target dependency object, stores the second target dependency object in the map table, and then returns the second target dependency object. An inline generic function is also provided as a singleton injection method. This method receives the type information corresponding to the second target dependency object and the first creation function corresponding to the second target dependency object. The singleton injection method flow is as follows: First, a corresponding type key is generated based on the type information corresponding to the second target dependency object as the second target retrieval key. Then, the object retrieval method of the singleton registry object is called, passing in the type key and the corresponding first creation function, to retrieve or create the singleton dependency object and return it.
[0176] 7) Implement parameter injection code generation This code generation method, implemented through annotation processors or compiler plugins, generates code for dependency injection. Developers mark the target function (to be injected) with a second injection annotation and the target parameters within that function with the first injection annotation. The code generation method analyzes the function signature, identifies the target parameters with the first injection annotation, and obtains their type and / or name information. It then generates a helper function whose name is a modified version of the target function's name with a suffix indicating it's a generated helper function. The helper function's signature removes the target parameters, retaining only the other parameters. Inside the helper function, a dependency retrieval method is first called to obtain the dependency objects to be injected. Then, the target function is called, passing the retrieved dependency objects as parameters. Thus, the caller only needs to invoke the generated helper function to automatically complete dependency injection.
[0177] Figure 2 A schematic diagram of the implementation flow of a code execution method provided in this embodiment of the disclosure. Figure 2 ,like Figure 2 As shown, the code execution method includes the following steps S201 to S205: Step S201, coroutine starts; Step S202, Dependency Registration Phase; During the dependency registration phase, the developer calls the scope injection method, passing in key-value pairs of the dependency objects. The system then stores each dependency object in the key-value pairs into the coroutine's local storage.
[0178] In the Kotlin implementation, dependency context elements can be used as coroutine context elements to store dependency objects.
[0179] Step S203, Dependency transitive phase; During the dependency transitive phase, when a coroutine executes a method call, the coroutine's local storage is automatically passed along the method call stack, and all methods in that method call chain can access the dependent objects stored in the local storage.
[0180] Step S204, Dependency retrieval stage; During the dependency retrieval phase, when a method in the method call chain requires a dependency object, the dependency retrieval method is invoked. This method retrieves the dependency object from the current coroutine's local storage, and can retrieve the corresponding dependency object by type key or string key and return it.
[0181] In the Kotlin implementation, the dependency object can be obtained from the dependency context element in the current coroutine's coroutine context.
[0182] Step S205, Dependency Cleanup Phase.
[0183] When the code block specified in the scope injection method finishes execution, the system automatically removes the temporarily injected dependency object from the coroutine's local storage and restores the coroutine context to the state before the dependency object was injected.
[0184] (ii) Dependency Injection Supporting Lazy Initialization This embodiment can also implement the following functions to increase support for lazy initialization (i.e., lazy injection) of dependent objects: 1) Define a lazy dependency wrapper class Define a generic lazy dependency wrapper class. Internally, this wrapper class maintains a nullable target cache field and a second creation function for creating the third target dependency object to be lazy-injected. The dependency object retrieval method is used to retrieve the dependency object. When this method executes, it first checks if the target cache field is null. If it is, it calls the second creation function to create the third target dependency object and stores it in the cache field, then returns the cached third target dependency object. If the target cache field is not null, it directly returns the cached third target dependency object. This achieves lazy initialization and one-time creation of dependency objects.
[0185] In some implementations, this delayed dependency wrapper class can be implemented using anonymous methods.
[0186] 2) Implement the delayed injection method An inline generic function is provided as a delayed injection method. This method receives the type information corresponding to the target delayed dependency wrapper class and the second creation function corresponding to the third target dependency object to be delayed injected. The method execution flow is as follows: First, the coroutine context of the current coroutine is obtained, and the dependency context element is retrieved from the coroutine context. If it does not exist, an exception is thrown. Then, a type key is generated based on the type information of the delayed dependency wrapper class as the third target retrieval key. Next, the target delayed dependency wrapper object is retrieved from the dependency context element according to the third target retrieval key. If it already exists, the target delayed dependency wrapper object is returned directly; if it does not exist, the target delayed dependency wrapper object corresponding to the target delayed dependency wrapper class is created using the third creation function based on the type information of the target delayed dependency wrapper class, the target delayed dependency wrapper object is stored in the dependency context element, and then the target delayed dependency wrapper object is returned.
[0187] 3) Use delayed injection When using lazy dependency injection, developers call the method, passing in the type information of the target lazy dependency wrapper class and the second creation function corresponding to the third target dependency object to be lazy-injected. The third target dependency object is not created immediately; instead, a target lazy dependency wrapper object is returned. The application can perform other operations in subsequent code. When the third target dependency object is actually needed, the dependency object retrieval method of the wrapper object is called. On the first call, this dependency object retrieval method executes the second creation function to create and cache the third target dependency object. Subsequent calls directly return the cached third target dependency object. This achieves the effect of on-demand creation and lazy initialization.
[0188] The code execution method provided in this disclosure, which implements dependency injection based on coroutines, has at least the following beneficial effects: 1) Reduced contractual dependencies and increased flexibility: This solution does not rely on specific annotation names, naming rules, or configuration file formats. Developers can complete dependency injection simply by using function calls, making the code more intuitive and flexible. Globally unique type keys are automatically generated using type inference mechanisms, eliminating the need for developers to manually specify key names.
[0189] 2) Significantly improves debuggability, making dependency injection explicit and traceable: Dependency injection is implemented through explicit function calls, generating ordinary, debuggable code that does not rely on reflection or proxy mechanisms. Developers can set breakpoints at injection and retrieval points to directly observe the propagation of dependent objects, and error messages are more intuitive and accurate.
[0190] 3) Natural Support for Method Call Stack Scope: This solution leverages the automatic propagation of coroutine local storage along the method call stack to achieve scope management based on natural call boundaries. Dependency objects are stored in coroutine local storage and are automatically propagated to the entire method call stack as the coroutine executes, requiring no explicit configuration. Dependency objects are automatically passed in the method call chain, eliminating the need for explicit configuration and breaking free from strong coupling with specific backend frameworks.
[0191] In related technologies, the scope of dependent objects is predefined and fixed, and tightly bound to specific backend frameworks (such as web frameworks). For example, the Request scope must be bound to the lifecycle of an HTTP request, and the Session scope must be bound to an HTTP session. The scope management of this disclosure is based on the natural execution boundaries and method call stack of coroutines, and does not depend on specific framework concepts. It can be applied to any environment, including non-web environments or custom call contexts. Developers can implement fine-grained scope control based on natural call boundaries, such as "for the same request, binding a singleton dependent object within one method call chain, while another method call chain can create a new dependent object."
[0192] 4) Supports complex tree-like dependency injection requirements, satisfying fine-grained dependency management: Because this solution supports nested scope injection methods within method call stacks of arbitrary depth, developers can nest scope injection methods in different method call branches to achieve a complex tree-like dependency injection structure. For example, global dependencies can be injected in the root method, branch-specific dependencies can be injected in a sub-method branch, and finer-grained dependencies can be injected in deeper sub-methods. This tree structure allows dependencies at different levels to be naturally isolated and shared, and inner scopes can access outer dependencies, meeting the fine-grained dependency management needs in complex business scenarios.
[0193] Figure 3 This is a schematic diagram of a tree-like dependency injection structure provided in an embodiment of this disclosure, such as... Figure 3As shown, singleton dependency objects can be injected into the root coroutine R, and the scope of the singleton dependency object is the entire lifecycle of the application; request-level dependency objects can be injected into request coroutines (such as request coroutine A, request coroutine B, and request coroutine C), and the scope of the request-level dependency object is the single request lifecycle of the corresponding request coroutine; method-level dependency objects can be injected into methods (such as method A1, method A2, method B1, and method C1), and the scope of the method-level dependency object is the method call stack lifecycle of the corresponding method; local dependency objects can be injected into deep methods (such as method A1-1, method A2-1, and method B1-1), and the scope of the local dependency object is the method call stack lifecycle (i.e., the nested scope lifecycle) of the corresponding deep method.
[0194] 5) Flexible scope control: Developers can temporarily inject or override dependent objects at any point using scope injection methods, achieving dynamic scope switching. It supports various fine-grained scope control methods, including coroutine level and method call stack level.
[0195] 6) Easy to implement temporary injection requirements: Through scope injection methods and delayed initialization mechanisms, temporary injection requirements such as conditional injection, runtime dependency replacement, and delayed creation can be easily implemented without complex configuration or proxy mechanisms.
[0196] 7) Provides precise control over the coroutine context, enabling fine-grained dependency isolation and sharing: Each coroutine has its own independent local storage space, and dependencies between different coroutines are completely isolated. Simultaneously, cross-coroutine dependency sharing can be achieved through a shared singleton registry object, providing precise isolation and sharing control.
[0197] 8) Reduce performance overhead and minimize the use of reflection and proxy mechanisms: This solution primarily uses coroutine local storage and ordinary function calls, avoiding a large number of reflection operations. The code generated by code generation technology is a direct type-safe call, with performance close to handwritten code, significantly reducing runtime overhead.
[0198] 9) Improve code readability: Dependency injection is implemented through explicit function calls, making dependencies visible in the code. Developers can directly see the injection and retrieval process of dependent objects in the code without having to look at configuration files or annotation definitions across files, thus improving code readability and maintainability.
[0199] 10) Type safety: By using type inference and type parameters obtained based on the reified mechanism, the system can check type matching at compile time, reducing runtime type conversion errors and providing better type safety.
[0200] 11) Easy to test: Since the dependency injection process is explicit, test dependencies can be easily injected through scope injection methods during testing, without the need for complex mocking frameworks or test container configurations.
[0201] Compared with related technologies, the embodiments disclosed herein have at least the following key differences: 1) Dependency Transmission Mechanism Based on Coroutine Local Storage: The core innovation of this disclosure lies in utilizing the coroutine local storage mechanism to transmit and manage dependency objects throughout the entire backend process. Unlike related technologies that use IoC containers and reflection mechanisms, this disclosure stores dependency objects in coroutine local storage. These dependency objects are automatically transmitted to the entire method call stack as the coroutine executes, without explicit configuration. This is the foundation for implementing natural method call stack scope management.
[0202] 2) Scope Management Based on Natural Method Call Stack: The scope management in this embodiment is based on the natural execution boundaries and method call stack of coroutines, rather than predefined scopes bound to a specific framework. Dependency objects are naturally passed along the method call stack, and developers can temporarily inject or override dependency objects at any location through scope injection methods, achieving dynamic scope switching. This is fundamentally different from related technologies that require explicit specification of predefined scopes.
[0203] 3) Unified Coroutine-Bound Lifecycle Management: This embodiment employs a unified dependency lifecycle management mechanism, where the lifecycle of all dependent objects is bound to a coroutine and determined by the coroutine that registers the dependency. The singleton pattern is implemented by registering dependencies on the root coroutine, the request-level pattern by registering dependencies on the request processing coroutine, and the nested scope pattern by registering dependencies at any position in the method call stack. This unified lifecycle management mechanism avoids the complexity of multiple scope types in related technologies.
[0204] 4) Explicit Parameter Injection Based on Code Generation: Embodiments of this disclosure automatically generate methods for reading or creating corresponding variables from coroutine local storage using code generation techniques (such as annotation processors or compiler plugins). The generated code is explicit, debuggable, and plain code, without relying on reflection or proxy mechanisms. Developers can directly view and debug the generated code. This is fundamentally different from related technologies that use reflection and proxy mechanisms.
[0205] 5) Support for nested tree-like dependency injection structures: This embodiment supports nested scope injection methods within a method call stack of arbitrary depth, enabling complex tree-like dependency injection structures. Dependencies at different levels can be naturally isolated and shared, inner scopes can access outer dependencies, and corresponding dependencies are automatically cleaned up when a scope ends. This tree-like structure meets the needs of fine-grained dependency management in complex business scenarios.
[0206] 6) Explicit Dependency Injection and Retrieval Interfaces: This embodiment implements dependency injection through explicit function calls (scope injection method and dependency retrieval method). Dependencies are explicitly visible in the code, eliminating the need to view configuration files or annotation definitions across files. This differs from related technologies that distribute dependencies across multiple configuration files and code files.
[0207] Based on the foregoing embodiments, this disclosure provides a code execution device, which includes various modules and units included in each module, and can be implemented by a processor in a computer device; of course, it can also be implemented by specific logic circuits; in the implementation process, the processor can be a central processing unit (CPU), a microprocessor unit (MPU), a digital signal processor (DSP), or a field programmable gate array (FPGA), etc.
[0208] Figure 4 This is a schematic diagram of the composition structure of a code execution device provided in an embodiment of the present disclosure, such as... Figure 4 As shown, the code execution device 400 includes: a first acquisition module 410, a storage module 420, and a first invocation module 430, wherein: The first acquisition module 410 is used to acquire the target code block to be called by the current coroutine, and at least one first dependency object that the target code block depends on; Storage module 420 is used to store at least one first dependent object in the local storage space of the current coroutine; The first calling module 430 is used to call and execute a target code block in the local storage space using the current coroutine, so as to obtain at least one first dependent object from the local storage space during the calling of the target code block.
[0209] In some embodiments, the storage module is further configured to: obtain the coroutine context of the current coroutine from the local storage space; add at least one first dependency object to the coroutine context to obtain the updated coroutine context; and store the updated coroutine context in the local storage space.
[0210] In some embodiments, the storage module is further configured to: retrieve the coroutine context to obtain a first target context element for storing dependent objects; add at least one first dependent object to the first target context element to obtain an updated first target context element; and generate an updated coroutine context based on the updated first target context element.
[0211] In some embodiments, the first target context element is used to store at least one first search key and a first dependency object corresponding to each first search key; the first calling module is further used to: obtain the coroutine context of the current coroutine from the local storage space during the invocation of the target code block; search the coroutine context to obtain the first target context element; determine the first target search key corresponding to the first target dependency object to be injected; and retrieve the first target dependency object from the first target context element using the first target search key, wherein the first target dependency object is used to invoke and execute the target code block.
[0212] In some embodiments, the storage module is further configured to: generate a first search key corresponding to the first dependent object based on the type information corresponding to the first dependent object; add the first search key corresponding to the first dependent object and the first dependent object as a key-value pair to the first target context element to obtain the updated first target context element; the first invocation module is further configured to: generate a first target search key corresponding to the first target dependent object based on the type information corresponding to the first target dependent object to be injected.
[0213] In some embodiments, the storage module is further configured to: generate a first retrieval key corresponding to the first dependent object based on the type information and name information corresponding to the first dependent object; the first invocation module is further configured to: generate a first target retrieval key corresponding to the first target dependent object based on the type information and name information corresponding to the first target dependent object to be injected.
[0214] In some embodiments, the code execution apparatus further includes: The second acquisition module is used to acquire the type information of the second target dependency object to be injected and the first creation function of the second target dependency object during the process of calling the target code block; The first generation module is used to generate the second target retrieval key based on the type information corresponding to the second target dependency object; A creation module is used to create a second target dependency object based on the type information of the second target dependency object when there is no second dependency object corresponding to the second target retrieval key in the target mapping table. The second target retrieval key and the second target dependency object are added to the target mapping table as key-value pairs. The target mapping table is shared across coroutines.
[0215] In some embodiments, the target code block includes a target function; the first calling module is further configured to: call an auxiliary calling function corresponding to the target function; the auxiliary calling function is configured to call a dependency retrieval method to obtain at least one first dependency object from the local storage space, and use the current coroutine to call and execute the target function with at least one first dependency object as a function parameter.
[0216] In some embodiments, the code execution apparatus further includes: The first removal module is used to remove at least one target parameter with the first injection annotation from the first parameter list of the target function to obtain the second parameter list; the target parameter represents the first dependency object on which the target function depends; The determination module is used to determine the second function name based on the first function name of the objective function and preset identification information; The second generation module is used to generate an auxiliary calling function based on a second parameter list, a second function name, and at least one target parameter. The function body of the auxiliary calling function includes a first code segment and a second code segment. The first code segment is used to call a dependency retrieval method based on the target parameter to obtain a first dependency object corresponding to the target parameter from the local storage space. The second code segment is used to use the current coroutine to call and execute the target function with at least one first dependency object as a function parameter.
[0217] In some embodiments, the code execution apparatus further includes: The third acquisition module is used to acquire the type information corresponding to the target delayed dependency wrapper class and the second creation function corresponding to the third target dependency object to be delayed injected during the process of calling the target code block; The fourth acquisition module is used to retrieve the target delayed dependency wrapper object corresponding to the target delayed dependency wrapper class from the local storage space based on the type information corresponding to the target delayed dependency wrapper class; the target delayed dependency wrapper object has a dependency object acquisition method, which is used to create the third target dependency object using the second creation function; The second calling module is used to call the dependency object retrieval method of the target delayed dependency wrapper object at the calling point corresponding to the third target dependency object, and obtain the third target dependency object.
[0218] In some embodiments, the target delayed dependency wrapper object also has a target cache field; the dependency object retrieval method of the target delayed dependency wrapper object is used to: create a third target dependency object using a second creation function when the target cache field is empty, store the third target dependency object in the target cache field, and return the third target dependency object; and retrieve and return the third target dependency object from the target cache field when the target cache field is not empty.
[0219] In some embodiments, the fourth acquisition module is further configured to: acquire the coroutine context of the current coroutine from local storage space; retrieve the coroutine context to obtain a second target context element; the second target context element is used to store at least one second search key and a delayed dependency wrapper object corresponding to each second search key; determine a third target search key corresponding to the target delayed dependency wrapper object based on the type information corresponding to the target delayed dependency wrapper class; and retrieve the target delayed dependency wrapper object from the second target context element using the third target search key.
[0220] In some embodiments, the code execution apparatus further includes a second removal module for removing at least one first dependency object from local storage space in response to the completion of execution of the target code block.
[0221] The descriptions of the apparatus embodiments above are similar to those of the method embodiments above, and have similar beneficial effects. In some embodiments, the functions or modules included in the apparatus provided in this disclosure can be used to perform the methods described in the method embodiments above. For technical details not disclosed in the apparatus embodiments of this disclosure, please refer to the descriptions of the method embodiments of this disclosure for understanding.
[0222] It should be noted that, in the embodiments of this disclosure, if the above methods are implemented as software functional modules and sold or used as independent products, they can also be stored in a computer-readable storage medium. Based on this understanding, the technical solutions of the embodiments of this disclosure, or the parts that contribute to related technologies, can be embodied in the form of a software product. This software product is stored in a storage medium and includes several instructions to cause a computer device (which may be a personal computer, server, or network device, etc.) to execute all or part of the methods of the various embodiments of this disclosure. The aforementioned storage medium includes various media capable of storing program code, such as USB flash drives, portable hard drives, read-only memory (ROM), magnetic disks, or optical disks. Thus, the embodiments of this disclosure are not limited to any specific hardware, software, or firmware, or any combination of hardware, software, and firmware.
[0223] This disclosure provides a computer device including a memory and a processor. The memory stores a computer program that can run on the processor. When the processor executes the program, it implements some or all of the steps in the above-described method.
[0224] This disclosure provides a computer-readable storage medium storing a computer program thereon, which, when executed by a processor, implements some or all of the steps in the above-described method. The computer-readable storage medium can be transient or non-transient.
[0225] This disclosure provides a computer program including computer-readable code. When the computer-readable code is executed in a computer device, a processor in the computer device performs some or all of the steps in the above-described method.
[0226] This disclosure provides a computer program product, which includes a non-transitory computer-readable storage medium storing a computer program. When the computer program is read and executed by a computer, it implements some or all of the steps in the above-described method. This computer program product can be implemented specifically through hardware, software, or a combination thereof. In some embodiments, the computer program product is specifically embodied as a computer storage medium; in other embodiments, the computer program product is specifically embodied as a software product, such as a software development kit (SDK), etc.
[0227] It should be noted that the descriptions of the various embodiments above tend to emphasize the differences between them, while their similarities or commonalities can be referenced interchangeably. The descriptions of the above embodiments of the device, storage medium, computer program, and computer program product are similar to the descriptions of the above method embodiments and have similar beneficial effects. For technical details not disclosed in the embodiments of the device, storage medium, computer program, and computer program product of this disclosure, please refer to the descriptions of the method embodiments of this disclosure for understanding.
[0228] It should be noted that, Figure 5 This is a schematic diagram of a hardware entity of a computer device in an embodiment of this disclosure, such as... Figure 5 As shown, the hardware entity of the computer device 500 includes: a processor 501, a communication interface 502, and a memory 503, wherein: Processor 501 typically controls the overall operation of computer device 500.
[0229] Communication interface 502 enables computer devices to communicate with other terminals or servers via a network.
[0230] The memory 503 is configured to store instructions and applications executable by the processor 501, and can also cache data to be processed or already processed (e.g., image data, audio data, voice communication data, and video communication data) in the processor 501 and various modules in the computer device 500. It can be implemented using flash memory or random access memory (RAM). Data transfer between the processor 501, the communication interface 502, and the memory 503 can be performed via bus 504.
[0231] It should be understood that the phrase "an embodiment" or "one embodiment" throughout the specification means that a specific feature, structure, or characteristic related to the embodiment is included in at least one embodiment of this disclosure. Therefore, "in one embodiment" or "one embodiment" appearing throughout the specification does not necessarily refer to the same embodiment. Furthermore, these specific features, structures, or characteristics can be combined in any suitable manner in one or more embodiments. It should be understood that in the various embodiments of this disclosure, the sequence numbers of the above steps / processes do not imply a sequential order of execution; the execution order of each step / process should be determined by its function and internal logic, and should not constitute any limitation on the implementation process of the embodiments of this disclosure. The sequence numbers of the above embodiments of this disclosure are merely descriptive and do not represent the superiority or inferiority of the embodiments.
[0232] It should be noted that, in this document, the terms "comprising," "including," or any other variations thereof are intended to cover non-exclusive inclusion, such that a process, method, article, or apparatus that comprises a list of elements includes not only those elements but also other elements not expressly listed, or elements inherent to such a process, method, article, or apparatus. Unless otherwise specified, an element defined by the phrase "comprising one..." does not exclude the presence of other identical elements in the process, method, article, or apparatus that includes that element.
[0233] In the several embodiments provided in this disclosure, it should be understood that the disclosed devices and methods can be implemented in other ways. The device embodiments described above are merely illustrative. For example, the division of units is only a logical functional division, and in actual implementation, there may be other division methods, such as: multiple units or components may be combined, or integrated into another system, or some features may be ignored or not executed. In addition, the coupling, direct coupling, or communication connection between the various components shown or discussed may be through some interfaces, and the indirect coupling or communication connection between devices or units may be electrical, mechanical, or other forms.
[0234] The units described above as separate components may or may not be physically separate, and the components shown as units may or may not be physical units; they may be located in one place or distributed across multiple network units; some or all of the units may be selected to achieve the purpose of this embodiment according to actual needs. Furthermore, the functional units in the embodiments of this disclosure may all be integrated into one processing unit, or each unit may be a separate unit, or two or more units may be integrated into one unit; the integrated unit may be implemented in hardware or in a combination of hardware and software functional units.
[0235] Those skilled in the art will understand that all or part of the steps of the above method embodiments can be implemented by hardware related to program instructions. The aforementioned program can be stored in a computer-readable storage medium. When the program is executed, it performs the steps of the above method embodiments. The aforementioned storage medium includes various media that can store program code, such as mobile storage devices, read-only memory (ROM), magnetic disks, or optical disks.
[0236] Alternatively, if the integrated units described above are implemented as software functional modules and sold or used as independent products, they can also be stored in a computer-readable storage medium. Based on this understanding, the technical solution of this disclosure, or the part that contributes to related technologies, can be embodied in the form of a software product. This computer software product is stored in a storage medium and includes several instructions to cause a computer device (which may be a personal computer, server, or network device, etc.) to execute all or part of the methods of the various embodiments of this disclosure. The aforementioned storage medium includes various media capable of storing program code, such as mobile storage devices, ROMs, magnetic disks, or optical disks.
[0237] The above are merely embodiments of this disclosure, but the scope of protection of this disclosure is not limited thereto. Any variations or substitutions that can be easily conceived by those skilled in the art within the scope of the technology disclosed in this disclosure should be included within the scope of protection of this disclosure.
Claims
1. A code execution method, characterized in that, include: Obtain the target code block to be invoked in the current coroutine, and at least one first dependency object that the target code block depends on; Store the at least one first dependent object in the local storage space of the current coroutine; Using the current coroutine, the target code block is invoked and executed in the local storage space to obtain the at least one first dependent object from the local storage space during the invocation of the target code block; The step of storing the at least one first dependent object into the local storage space of the current coroutine includes: Obtain the coroutine context of the current coroutine from the local storage space; The coroutine context is retrieved to obtain a first target context element for storing dependent objects; Add the at least one first dependency object to the first target context element to obtain the updated first target context element; Based on the updated first target context element, an updated coroutine context is generated; The updated coroutine context is stored in the local storage space.
2. The code execution method according to claim 1, characterized in that, The first target context element is used to store at least one first search key and a first dependency object corresponding to each first search key; The step of retrieving the at least one first dependency object from the local storage space during the invocation of the target code block includes: During the invocation of the target code block, the coroutine context of the current coroutine is obtained from the local storage space; The first target context element is obtained by retrieving the coroutine context. Determine the first target retrieval key corresponding to the first target dependency object to be injected; Using the first target retrieval key, the first target dependency object is retrieved from the first target context element. The first target dependency object is used to call and execute the target code block.
3. The code execution method according to claim 2, characterized in that, Adding the at least one first dependency object to the first target context element to obtain the updated first target context element includes: Based on the type information corresponding to the first dependent object, a first search key corresponding to the first dependent object is generated; Add the first search key corresponding to the first dependent object and the first dependent object as a key-value pair to the first target context element to obtain the updated first target context element; The step of determining the first target retrieval key corresponding to the first target dependency object to be injected includes: Based on the type information corresponding to the first target dependency object to be injected, a first target retrieval key corresponding to the first target dependency object is generated.
4. The code execution method according to claim 3, characterized in that, The step of generating a first search key corresponding to the first dependent object based on the type information corresponding to the first dependent object includes: Based on the type information and name information corresponding to the first dependent object, a first search key corresponding to the first dependent object is generated. The step of generating a first target retrieval key corresponding to the first target dependency object based on the type information of the first target dependency object to be injected includes: Based on the type information and name information of the first target dependency object to be injected, a first target retrieval key is generated for the first target dependency object.
5. The code execution method according to claim 1, characterized in that, The method further includes: During the invocation of the target code block, the type information corresponding to the second target dependency object to be injected, and the first creation function corresponding to the second target dependency object are obtained; Based on the type information corresponding to the second target dependent object, a second target retrieval key is generated; If no second dependent object corresponding to the second target retrieval key exists in the target mapping table, the second target dependent object is created using the first creation function based on the type information corresponding to the second target dependent object, and the second target retrieval key and the second target dependent object are added as key-value pairs to the target mapping table; the target mapping table is shared across coroutines.
6. The code execution method according to claim 1, characterized in that, The target code block includes the target function; The step of utilizing the current coroutine to call and execute the target code block in the local storage space, so as to obtain the at least one first dependent object from the local storage space during the call of the target code block, includes: The auxiliary calling function corresponding to the target function is invoked; the auxiliary calling function is used to invoke the dependency retrieval method to obtain the at least one first dependency object from the local storage space, and use the current coroutine to call and execute the target function with the at least one first dependency object as a function parameter.
7. The code execution method according to claim 6, characterized in that, The method further includes: Remove at least one target parameter with a first injection annotation from the first parameter list of the objective function to obtain a second parameter list; the target parameter represents the first dependent object on which the objective function depends. Based on the first function name of the target function and the preset identification information, determine the second function name; Based on the second parameter list, the second function name, and at least one of the target parameters, the auxiliary calling function is generated; the function body of the auxiliary calling function includes a first code segment and a second code segment; the first code segment is used to call the dependency retrieval method based on the target parameter to obtain the first dependency object corresponding to the target parameter from the local storage space; the second code segment is used to use the current coroutine, taking the at least one first dependency object as a function parameter, to call and execute the target function.
8. The code execution method according to claim 1, characterized in that, The method further includes: During the invocation of the target code block, the type information corresponding to the target delayed dependency wrapper class and the second creation function corresponding to the third target dependency object to be delayed injection are obtained; Based on the type information corresponding to the target delayed dependency wrapper class, the target delayed dependency wrapper object corresponding to the target delayed dependency wrapper class is obtained from the local storage space; the target delayed dependency wrapper object has a dependency object acquisition method, which is used to create the third target dependency object using the second creation function; At the call point corresponding to the third target dependency object, the dependency object retrieval method of the target delayed dependency wrapper object is called to obtain the third target dependency object.
9. The code execution method according to claim 8, characterized in that, The target delayed dependency wrapper object also has a target cache field; the dependency object retrieval method of the target delayed dependency wrapper object is used for: If the target cache field is empty, the third target dependency object is created using the second creation function, the third target dependency object is stored in the target cache field, and the third target dependency object is returned. If the target cache field is not empty, retrieve and return the third target dependency object from the target cache field.
10. The code execution method according to claim 8, characterized in that, The step of retrieving the target delayed dependency wrapper object corresponding to the target delayed dependency wrapper class from the local storage space based on the type information corresponding to the target delayed dependency wrapper class includes: Obtain the coroutine context of the current coroutine from the local storage space; The coroutine context is retrieved to obtain a second target context element; the second target context element is used to store at least one second search key and a lazy dependency wrapper object corresponding to each second search key. Based on the type information corresponding to the target delayed dependency wrapper class, determine the third target retrieval key corresponding to the target delayed dependency wrapper object; Using the third target retrieval key, the target delayed dependency wrapper object is retrieved from the second target context element.
11. The code execution method according to any one of claims 1 to 10, characterized in that, The method further includes: In response to the completion of the execution of the target code block, the at least one first dependency object is removed from the local storage space.
12. A code execution device, characterized in that, include: The first acquisition module is used to acquire the target code block to be called by the current coroutine, and at least one first dependency object that the target code block depends on; A storage module is used to store the at least one first dependent object in the local storage space of the current coroutine; The first calling module is used to call and execute the target code block in the local storage space using the current coroutine, so as to obtain the at least one first dependent object from the local storage space during the calling of the target code block; The storage module is further configured to: obtain the coroutine context of the current coroutine from the local storage space; and retrieve the coroutine context to obtain a first target context element for storing dependent objects. Add the at least one first dependency object to the first target context element to obtain the updated first target context element; Based on the updated first target context element, an updated coroutine context is generated; the updated coroutine context is stored in the local storage space.
13. A computer device comprising a memory and a processor, the memory storing a computer program executable on the processor, characterized in that, When the processor executes the program, it implements the steps of the method according to any one of claims 1 to 11.
14. A computer-readable storage medium having a computer program stored thereon, characterized in that, When the computer program is executed by a processor, it implements the steps of the method according to any one of claims 1 to 11.
15. A computer program product, comprising a computer program or instructions, characterized in that, When the computer program or instructions are executed by a processor, they implement the steps of the method according to any one of claims 1 to 11.
