DI System — Aquilia Documentation
Comprehensive guide and documentation for DI System in the Aquilia framework. View API reference, examples, and implementation patterns.
Core Subsystems / Dependency Injection Dependency Injection Overview Aquilia's DI subsystem acts as the central nervous system of your web application. It integrates manifests, hierarchical scopes, request lifecycles, and controller resolution into a single O(1) lookup path completing in under 3µs. System Architecture Core Pillars , , , , , , ].map((card, i) => ( ))} Module Map The DI system lives under aquilia/di/ and is composed of 13 modules: Module Contents `).replace(/^_/, '')}`}> ))} Registration Flow The Registry.from_manifests() pipeline processes manifests through four sequential phases before building the container: , , , , ].map((p, i) => ( ))} from aquilia.di import Registry # Typically called by the engine during startup: registry = Registry.from_manifests( manifests=[users_manifest, orders_manifest, payments_manifest], config=app_config, enforce_cross_app=True, # Strict in production ) # Build the root container container = registry.build_container() await container.startup() # Run lifecycle hooks Resolution Hot Path resolve_async() is the primary resolution method called on every request. It is optimized for <3µs cached lookups with an inlined token-to-key conversion path: # Simplified view of resolve_async internals: async def resolve_async(self, token, *, tag=None, optional=False): # 1. Inline token_to_key (avoid function-call overhead) # Uses _type_key_cache (dict) for O(1) type → string lookup key = self._type_key_cache.get(token) or self._token_to_key(token) # 2. Check cache first — O(1) dict lookup cache_key = f" : " if tag else key cached = self._cache.get(cache_key) if cached is not _SENTINEL: return cached # Usage inside Web Framework Aquilia promotes clean separation of concerns. Do not manually pull dependencies from the request container. Instead, use Constructor Injection to automatically wire services, repositories, and models. 1. Define and Annotate Services ") async def get_user(self, ctx): # Use constructor injected service directly user = await self.user_service.get_user(ctx.request.params["user_id"]) return ctx.json(user) Anti-Pattern Warning Do NOT resolve dependencies dynamically inside routes via await ctx.container.resolve_async(UserService). This hides dependencies, makes unit testing complex, and prevents compile-time dependency cycle and scope validation checks. Always prefer Constructor Injection. Provider Types at a Glance Provider Use Case Async Init `).replace(/^_/, '')}`}> ))} Error Taxonomy All DI errors inherit from DIError and include rich diagnostic messages with file locations, candidate lists, and suggested fixes: Error Trigger Suggested Fix `).replace(/^_/, '')}`}> ))} CLI Tooling The DI system provides five CLI commands for validation, visualization, and profiling: Command Description ))} Container )
Go to Homepage