Tiny, fast, zero-boilerplate runtime Dependency Injection (DI) framework for Java.
- Why Dimension-DI?
- Core Philosophy
- Requirements
- Installation
- Usage
- 1. Define Your Components
- 2. Configure and Initialize
- Members Injection: Fields and Methods (Optional)
- Binding Interfaces and Named Implementations
- Named implementations via @Named
- Custom Providers (like @Provides)
- Skipping Scanning (Manual Wiring Only)
- Testing and Overriding
- Assisted Injection (Factory Pattern)
- How It Works
- Design Notes: DI vs Service Locator
- Limitations
- API Cheatsheet
- Comparison Tables
- Documentation
- DI Containers Comparison
- Notice
- Contact
This framework provides dependency injection (DI) based on JSR-330 (jakarta.inject.*) annotations. It automatically discovers and wires your application's components through constructor injection, leveraging classpath scanning near a zero-configuration setup. Designed for simplicity and fast startup, it's perfect for smaller applications, microservices, and tools that need the benefits of DI without the overhead associated with larger frameworks like Spring, Guice, and Dagger 2.
Mermaid schema
graph TB
subgraph config["⚙️ Configuration JSR-330"]
direction LR
CA["@Inject<br/>Constructor"] --> CB["@Singleton<br/>Scope"] --> CC["@Named<br/>Qualifier"]
end
subgraph container["📦 DI Container"]
direction LR
ContainerDesc["<large>API Scans bytecode <br/>via JDK Class-File API</large>"] --> D1["DependencyScanner"] --> D2["Provider Registry"] --> D3["ServiceLocator"]
end
subgraph injection["💉 Dependency Resolution"]
direction LR
InjectionDesc["<large>Implements the Service<br/>Locator design pattern</large>"] --> I1["Request Type"] --> I2["Check Cache"] --> I3["Create Instance"] --> I4["Return Object"]
end
config -->|is analyzed by| container
container -->|resolves dependencies via| injection
injection -->|provides entrypoint to| APP["🎯 Your App<br/><small>Composition Root</small>"]
%% Styles
classDef configClass fill:#e3f2fd,stroke:#90caf9,stroke-width:2px,color:#333
classDef containerClass fill:#fff3e0,stroke:#ffcc80,stroke-width:2px,color:#333
classDef injectionClass fill:#f3e5f5,stroke:#ce93d8,stroke-width:2px,color:#333
classDef appClass fill:#e8f5e9,stroke:#a5d6a7,stroke-width:2px,color:#333
classDef descClass fill:none,stroke:none,color:#555,font-size:12px,font-style:italic
class CA,CB,CC configClass
class D1,D2,D3 containerClass
class I1,I2,I3,I4 injectionClass
class APP appClass
class CHeader descClass
Dimension-DI is a lightweight, runtime-oriented dependency injection container designed for simplicity and performance. It delivers the essential features you need without the complexity:
- Standards-Based: Uses JSR-330 (@Inject, @Named) for clean, constructor-injected code.
- Powerful & Safe: Features @Singleton scoping, circular dependency detection, and explicit binding for interfaces.
- Fast & Efficient: Employs classpath scanning via the JDK Class-File API (without loading classes) for rapid startup, working seamlessly from both directories and JARs.
- Minimal Overhead: No proxies, bytecode generation, or runtime magic—just a simple, thread-safe service locator under the hood that you'll never need to touch in your business logic.
Dimension-DI follows a two-phase approach:
- Build-Time Configuration: A fluent
BuilderAPI is used to configure the DI container. This phase involves scanning the classpath for components marked with@Inject, analyzing their dependencies, and registering providers (recipes for creating objects). This is where the "DI" part shines. - Runtime Resolution: At runtime, dependencies are resolved using an internal, globally accessible
ServiceLocator. While the implementation uses a Service Locator, the design encourages you to write your application code using pure Constructor Injection, decoupling your components from the DI framework itself.
- Java 25+ with JDK Class-File API.
To use Dimension-DI in your Maven project, add the following dependency to your pom.xml:
<dependency>
<groupId>ru.dimension</groupId>
<artifactId>di</artifactId>
<version>${revision}</version>
</dependency>Create your services and components using standard jakarta.inject.* annotations. Your classes should not have any knowledge of Dimension-DI.
import jakarta.inject.Inject;
import jakarta.inject.Singleton;
@Singleton
class Config {
String url() { return "https://api.example.com"; }
}
class ApiClient {
private final Config config;
@Inject
ApiClient(Config config) {
this.config = config;
}
}
class App {
private final ApiClient api;
@Inject
App(ApiClient api) {
this.api = api;
}
void run() {}
}Scan your base packages and get entry point from ServiceLocator
import ru.dimension.di.DimensionDI;
import ru.dimension.di.ServiceLocator;
public class Main {
public static void main(String[] args) {
DimensionDI.builder()
.scanPackages("com.example")
.buildAndInit();
App app = ServiceLocator.get(App.class);
app.run();
}
}All dependencies are resolved via constructor injection. @Singleton classes are cached.
While constructor injection is highly recommended for mandatory dependencies, Dimension-DI also supports field and method injection. This is useful for optional dependencies or for integrating with frameworks that require it.
Field Injection
Annotate a non-final field with @Inject. The container will set its value after the object is constructed.
import jakarta.inject.Inject;
import jakarta.inject.Named;
class NotificationService {
@Inject private EmailSender emailSender;
@Inject @Named("sms")
private MessageSender smsSender;
public void notify(User user, String message) {
emailSender.send(user.getEmail(), message);
}
}Method Injection
Annotate a method with @Inject. The container will resolve its parameters and invoke it after construction.
class MyService {
private DependencyA depA;
// Must have an injectable constructor (e.g., public no-arg)
public MyService() {}
@Inject
public void initialize(DependencyA depA) {
// This method is called by the container after construction
this.depA = depA;
}
}Note: Members injection (both field and method) occurs after the constructor is called. The order of injection between fields and methods is not guaranteed. Final fields cannot be injected.
When injecting interfaces, add a binding so the container knows which implementation to use.
import jakarta.inject.Inject;
interface Transport { }
class HttpTransport implements Transport {
@Inject HttpTransport(Config cfg) { }
}
class Service {
@Inject Service(Transport transport) { }
}Bind interface to implementation
import ru.dimension.di.DimensionDI;
public class Main {
public static void main(String[] args) {
DimensionDI.builder()
.scanPackages("com.example")
.bind(Transport.class, HttpTransport.class)
.buildAndInit();
}
}import jakarta.inject.Inject;
import jakarta.inject.Named;
interface Cache {}
class RedisCache implements Cache { @Inject RedisCache(Config c) { } }
class InMemoryCache implements Cache { @Inject InMemoryCache() { } }
class Repository {
@Inject Repository(@Named("fast") Cache cache) { }
}import ru.dimension.di.DimensionDI;
public class Main {
public static void main(String[] args) {
DimensionDI.builder()
.scanPackages("com.example")
.bindNamed(Cache.class, "fast", InMemoryCache.class)
.bindNamed(Cache.class, "durable", RedisCache.class)
.buildAndInit();
}
}For objects that need custom construction logic (heavy init, load from file/env, etc)
import ru.dimension.di.DimensionDI;
public class Main {
public static void main(String[] args) {
DimensionDI.builder()
.scanPackages("com.example")
.provide(Config.class, ServiceLocator.singleton(() -> {
{ }
return new Config();
}))
.buildAndInit();
}
}Use ServiceLocator.singleton(supplier) to cache the result.
import ru.dimension.di.DimensionDI;
public class Main {
public static void main(String[] args) {
DimensionDI.builder()
.scanPackages("com.example")
.provideNamed(Cache.class, "fast", ServiceLocator.singleton(InMemoryCache::new))
.buildAndInit();
}
}If you cannot or do not want to use the Class-File API
import ru.dimension.di.DimensionDI;
import ru.dimension.di.ServiceLocator;
public class Main {
public static void main(String[] args) {
DimensionDI.builder()
.provide(Config.class, ServiceLocator.singleton(Config::new))
.provide(ApiClient.class, () -> new ApiClient(ServiceLocator.get(Config.class)))
.provide(App.class, () -> new App(ServiceLocator.get(ApiClient.class)))
.buildAndInit();
}
}Swap implementations in tests without changing source
import ru.dimension.di.DimensionDI;
import ru.dimension.di.ServiceLocator;
class FakeApiClient extends ApiClient { }
void setupTest() {
DimensionDI.builder()
.scanPackages("com.example")
.provide(ApiClient.class, FakeApiClient::new)
.buildAndInit();
}Override at runtime
@Test
void runTest() {
ServiceLocator.override(ServiceLocator.Key.of(ApiClient.class), FakeApiClient::new);
}Reset
@Test
void runTest() {
ServiceLocator.clear();
}When you need to create objects that require both DI-managed dependencies and runtime parameters, use Assisted Injection. This pattern uses factory interfaces to combine injected singletons with caller-provided values.
import jakarta.inject.Inject;
import ru.dimension.di.Assisted;
class UserSession {
private final String sessionId;
private final int timeout;
private final SessionManager manager; // from DI
private final Logger logger; // from DI
@Inject
UserSession(@Assisted String sessionId,
@Assisted int timeout,
SessionManager manager,
Logger logger) {
this.sessionId = sessionId;
this.timeout = timeout;
this.manager = manager;
this.logger = logger;
}
}interface UserSessionFactory {
UserSession create(String sessionId, int timeout);
}import ru.dimension.di.Assisted;
import ru.dimension.di.DimensionDI;
import ru.dimension.di.ServiceLocator;
import jakarta.inject.Inject;
// 1. Factory interface (must be defined)
// The method name can be anything; only parameter types and order matter
interface UserSessionFactory {
UserSession create(String sessionId, int timeoutSeconds);
}
// 2. Target class (must be defined)
class UserSession {
private final String sessionId;
private final int timeout;
// @Inject is required on the constructor
// Parameters passed via the factory must be annotated with @Assisted
@Inject
public UserSession(@Assisted String sessionId,
@Assisted int timeout,
SomeDependency dependency) { // SomeDependency will be resolved from DI
this.sessionId = sessionId;
this.timeout = timeout;
System.out.println("Session created: " + sessionId + ", dependency: " + dependency);
}
}
// Simple dependency for example purposes
class SomeDependency {
@Inject
public SomeDependency() {}
}
// 3. Usage (your code inside main)
public class Main {
public static void main(String[] args) {
DimensionDI.builder()
.scanPackages("com.example") // Scans for injectable classes like SomeDependency
// Register the factory and bind it to the UserSession implementation
.bindFactory(UserSessionFactory.class, UserSession.class)
.buildAndInit();
// Get factory from DI
UserSessionFactory factory = ServiceLocator.get(UserSessionFactory.class);
// Create instances with runtime parameters
UserSession session1 = factory.create("sess-001", 3600);
UserSession session2 = factory.create("sess-002", 7200);
}
}For simpler cases, create instances directly without defining a factory interface:
UserSession session = ServiceLocator.create(UserSession.class, "sess-001", 3600);When you have multiple parameters of the same type, use named @Assisted annotations:
class Connection {
@Inject
Connection(@Assisted("host") String host,
@Assisted("backup") String backupHost,
ConnectionPool pool) {
// ...
}
}
interface ConnectionFactory {
Connection create(@Assisted("host") String host,
@Assisted("backup") String backupHost);
}Note: Factory interfaces are singletons by default. Each factory call creates a new instance of the target class, with DI dependencies (like @Singleton) properly shared across all created instances.
- Scans configured packages for concrete classes with:
- an
@Injectconstructor, or - a public no-arg constructor
- an
- Reads
@Singletonand implemented interfaces - Uses the JDK Class-File API to inspect bytecode without loading classes
- Builds a provider map from scanned results
- Adds manual
bindandprovideentries (manual overrides win) - Initializes the ServiceLocator with providers
- Thread-safe registry of
Key -> Supplier<?> - Resolves constructor parameters on-demand (supports
@Named) - Smart fallback resolution:
- Named requests fall back to unnamed bindings when named not found
- Unnamed requests resolve to unique named bindings when no unnamed exists
- Manual bindings override scanned bindings during auto-aliasing
- Helpful error messages show available bindings on resolution failure
- Performs members injection (fields and methods) after construction
- Supports
@Injecton fields and methods, including@Namedqualifiers - Detects circular dependencies and throws with a helpful stack
- Caches singletons via
SingletonSupplier
Note: Fallback behavior can be disabled for stricter DI semantics using setNamedFallbackEnabled(false) and setUnnamedFallbackEnabled(false).
- You write normal constructor-injected code with
@Inject. This is DI-friendly. - Internally, the container uses a simple service locator
ServiceLocatorfor resolution. - Best practice: only call
ServiceLocator.get(...)at the composition root (for example, to get your top-levelApp).
- Only Jakarta Inject annotations are supported:
@Inject(on constructors, fields, and methods)@Singleton@Named(on constructor parameters, fields, and method parameters)
- Field injection works on
private,protected, andpublicnon-final fields, including inherited ones. - Named/unnamed fallback is enabled by default for convenience; disable for strict mode.
- Manual bindings override scanned bindings when auto-aliasing is enabled.
- Not yet supported:
- Custom qualifiers beyond
@Named Provider<T>, multi-bindings (collections), scopes beyond singleton
- Custom qualifiers beyond
- Scanning uses the JDK Class-File API (Java 24+).
DimensionDI.builder().scanPackages(...).bind(...).provide(...).buildAndInit();
ServiceLocator.get(MyRoot.class)
.provide(type, supplier)— Registers a custom provider for a type.provideNamed(type, name, supplier)— Registers a provider for a named type.provideSingleton(type, supplier)— Registers a singleton provider.bind(interface, impl)— Binds an interface to an implementation.bindNamed(interface, name, impl)— Binds a named interface to an implementation.bindFactory(factoryInterface, targetClass)— Registers an assisted injection factory.bindFactory(factoryInterface)— Registers factory (target inferred from return type).autoAliasUniqueNamed(boolean)— Enable/disable auto-aliasing for unique named bindings (default: true)
ServiceLocator.create(type, assistedArgs...)— Creates instance with runtime parametersServiceLocator.createFactory(factoryInterface, targetClass)— Creates a factory implementation@Assisted— Marks constructor parameter as runtime-provided@Assisted("name")— Named assisted parameter for disambiguation
ServiceLocator.singleton(supplier)— Caches an instance.ServiceLocator.override(key, supplier)— Replaces a provider at runtime.ServiceLocator.alias(aliasKey, targetKey)— Creates an alias for a provider.ServiceLocator.clear()— Resets the entire registry.ServiceLocator.setNamedFallbackEnabled(boolean)— Enable/disable named→unnamed fallback (default: true).ServiceLocator.setUnnamedFallbackEnabled(boolean)— Enable/disable unnamed→named fallback (default: true).
| Feature | Dimension-DI | Spring IoC | Google Guice | Dagger 2 |
|---|---|---|---|---|
| Annotation Standard | JSR-330 (Jakarta) | Spring-specific + JSR-330 | JSR-330 | JSR-330 + custom |
| Dependency Injection | Constructor, field, method | Constructor, field, method | Constructor, field, method | Constructor-based |
| Learning Curve | ⭐ Minimal | ⭐⭐⭐⭐⭐ Steep | ⭐⭐⭐ Moderate | ⭐⭐⭐ Moderate |
| Performance | ⭐⭐⭐⭐⭐ Very High | ⭐⭐ Slow | ⭐⭐⭐ Medium | ⭐⭐⭐⭐⭐ Fastest |
| Startup Time | Ultra-fast | Slow | Fast | Instant (compile-time) |
| Runtime metadata | JDK Class-File API | Dynamic reflection | Dynamic reflection | None (compile-time) |
| Bytecode Generation | None | Extensive proxies | Extensive proxies | Compile-time only |
| Scoping | @Singleton | Request, Session, Singleton, Prototype | Singleton, custom | Singleton, custom |
| @Singleton Support | ✅ Yes | ✅ Yes | ✅ Yes | ✅ Yes |
| @Named Qualifiers | ✅ Yes | ✅ Yes | ✅ Yes | ✅ Yes |
| Custom Providers | ✅ provide() |
✅ @Bean |
✅ @Provides |
✅ @Provides |
| Assisted Injection | ✅ @Assisted + Factory |
❌ Manual | ✅ AssistedInject | ✅ @AssistedInject |
| Field Injection | ✅ Yes | ✅ Yes | ✅ Yes | ✅ Yes (members injection) |
| Method Injection | ✅ Yes | ✅ Yes | ✅ Yes | ✅ Yes (members injection) |
| Collections/Multi-bind | ❌ No | ✅ Yes | ✅ Yes | ✅ Yes (@IntoSet/@IntoMap) |
| Named/Unnamed Fallback | ✅ Automatic | ❌ No | ❌ No | ❌ No |
| Circular detection | ✅ Yes, explicit | ✅ Yes | ✅ Yes | ✅ Compile-time |
| Module/Config System | Fluent Builder | @Configuration + XML |
Module classes |
Component interface |
| Testing Support | ✅ Override, Clear | ✅ Profiles, Mocks | ✅ Binding override | ✅ Test components |
| JAR/Directory Scanning | ✅ Both | ✅ Both | Manual by default | N/A (compile-time) |
| Framework Size | ~19KB | ~10MB+ | ~782Kb | ~47Kb |
| Best For | Microservices, Tools, Minimal overhead | Enterprise apps, full web stack | Medium projects, modular | Android, compile-safety |
| Zero Configuration | ✅ Full classpath scan | Manual registration | Compile-time setup |
| Feature | Dimension-DI | PicoContainer | HK2 | Avaje Inject |
|---|---|---|---|---|
| Annotation Standard | JSR-330 | Custom only | JSR-330 | JSR-330 |
| Lightweight | ✅ Ultra-light | ✅ Very light | ✅ Light | |
| Classpath Scanning | ✅ Class-File API | ❌ Manual only | ✅ Yes | ✅ Yes |
| Constructor Injection | ✅ Yes | ✅ Yes | ✅ Yes | ✅ Yes |
| Field Injection | ✅ Yes | ✅ Yes | ✅ Yes | ✅ Yes |
| Method Injection | ✅ Yes | ✅ Yes | ✅ Yes | ✅ Yes |
| Scoping | @Singleton | Singleton | Singleton, request, custom | Singleton, custom |
| @Named Qualifiers | ✅ Yes | ❌ No | ✅ Yes | ✅ Yes |
| Custom Providers | ✅ provide() |
✅ Manual factories | ✅ @Factory |
✅ @Factory |
| Circular Dependency Detection | ✅ Explicit error | ❌ Runtime error | ✅ Yes | ✅ Yes |
| Performance | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| Startup Time | Ultra-fast | Very fast | Fast | Fastest (compile-time) |
| Runtime Reflection | Minimal | Extensive | Moderate | None (compile-time) |
| Service Locator Pattern | ✅ Internal only | ✅ Primary model | ✅ HK2ServiceLocator | ✅ Internal only |
| Compilation Model | Runtime scan | Manual registration | Runtime scan | Compile-time (APT) |
| Maven Integration | ✅ Easy | ✅ Easy | ✅ Easy (Jersey) | ✅ Easy (APT) |
| Testing Support | ✅ Override, Clear | ✅ Rebind | ✅ Yes | ✅ Yes |
| Framework Size | ~19KB | ~327KB | ~131Kb | ~80KB |
| Active Development | ✅ Modern | ✅ Active | ✅ Active | |
| Jakarta Inject Ready | ✅ Full | ✅ Yes | ✅ Yes | |
| Best For | Microservices, fast startup | Embedded, custom, legacy | OSGi, modular systems | Compile-safe DI, GraalVM |
| Java Version | 25+ | 8+ | 8+ | 11+ |
Using source code of DI Containers Comparison project.
Processor: AMD Ryzen 5 5600H with Radeon Graphics, 3301 Mhz, 6 Core(s), 12 Logical Processor(s)
Memory: 16.0 GB
Disk: Generic Flash Disk USB Device<br>- SAMSUNG MZVL2512HCJQ-00B00 (476.94 GB)
OS: Microsoft Windows 11 (WSL2)
java version "25.0.1" 2025-10-21 LTS
Java(TM) SE Runtime Environment (build 25.0.1+8-LTS-27)
Java HotSpot(TM) 64-Bit Server VM (build 25.0.1+8-LTS-27, mixed mode, sharing)
| DI | Jar w/Deps Size, Mb | ⬇️ Wall, ms | User, ms | Sys, ms | Max RSS, Mb | Allocated, Mb | Alloc Count | LoC |
|---|---|---|---|---|---|---|---|---|
| jvm | 1.75 | 79.30 | 23.20 | 18.40 | 41.38 | 0.25 | 6 | 2 |
| DI | Jar w/Deps Size, Mb | ⬇️ Wall, ms | User, ms | Sys, ms | Max RSS, Mb | Allocated, Mb | Alloc Count | LoC |
|---|---|---|---|---|---|---|---|---|
| baseline | 1.75 | 100.30 | 47.00 | 22.10 | 43.54 | 0.25 | 6 | 24 |
| kotlin-lazy | 1.75 | 101.70 | 53.30 | 20.90 | 43.73 | 0.25 | 7 | 31 |
| dagger | 1.82 | 157.40 | 59.80 | 27.40 | 43.73 | 0.26 | 8 | 51 |
| cayennedi | 1.82 | 160.50 | 119.00 | 30.60 | 51.27 | 0.25 | 8 | 49 |
| dimension | 1.78 | 178.70 | 136.50 | 35.90 | 54.57 | 0.28 | 12 | 37 |
| kodein | 3.43 | 248.30 | 173.10 | 42.70 | 53.92 | 2.41 | 33 | 32 |
| koin | 2.22 | 283.90 | 180.90 | 49.80 | 58.18 | 2.15 | 38 | 31 |
| koin-reflect | 2.22 | 288.70 | 183.70 | 50.40 | 56.79 | 2.32 | 39 | 33 |
| komok-to-be-injected | 2.48 | 296.00 | 157.90 | 49.80 | 53.41 | 2.56 | 34 | 33 |
| bootique | 4.69 | 426.40 | 403.20 | 65.50 | 68.51 | 0.41 | 37 | 63 |
| spring-xml | 6.78 | 574.70 | 535.40 | 81.50 | 74.79 | 0.67 | 66 | 37 |
| guice | 5.62 | 620.00 | 489.70 | 88.70 | 69.18 | 0.62 | 60 | 47 |
| spring | 6.78 | 653.60 | 601.70 | 94.30 | 71.25 | 1.17 | 92 | 38 |
| spring-index | 6.78 | 669.70 | 652.60 | 90.20 | 74.07 | 0.95 | 100 | 34 |
| spring-scan | 6.78 | 704.20 | 666.50 | 115.10 | 73.60 | 1.05 | 96 | 34 |
| owb | 3.30 | 712.70 | 702.20 | 98.00 | 74.61 | 0.74 | 75 | 49 |
| springboot | 10.33 | 1,845.00 | 2,346.50 | 215.60 | 110.21 | 2.45 | 355 | 56 |
| springboot-index | 10.33 | 1,850.70 | 2,259.60 | 228.50 | 109.98 | 2.18 | 336 | 45 |
| DI | Jar w/Deps Size, Mb | ⬇️ Wall, ms | User, ms | Sys, ms | Max RSS, Mb | Allocated, Mb | Alloc Count | LoC |
|---|---|---|---|---|---|---|---|---|
| baseline-deep | 1.88 | 175.70 | 110.80 | 32.90 | 44.27 | 0.25 | 11 | 719 |
| kotlin-lazy-deep | 1.89 | 254.00 | 240.60 | 45.30 | 56.30 | 0.39 | 26 | 925 |
| dagger-deep | 2.05 | 278.90 | 180.40 | 44.40 | 47.96 | 0.26 | 14 | 1145 |
| cayennedi-deep | 2.00 | 305.00 | 308.80 | 53.10 | 58.54 | 0.27 | 19 | 1953 |
| dimension-deep | 1.91 | 376.60 | 464.80 | 53.00 | 67.68 | 0.63 | 46 | 831 |
| koin-deep | 2.37 | 418.20 | 371.00 | 65.10 | 67.83 | 2.68 | 57 | 725 |
| komok-to-be-injected-deep | 2.62 | 456.20 | 358.30 | 65.20 | 67.63 | 2.83 | 57 | 927 |
| koin-reflect-deep | 2.52 | 478.30 | 349.90 | 74.80 | 61.65 | 2.75 | 55 | 727 |
| kodein-deep | 3.86 | 480.30 | 424.40 | 75.30 | 69.57 | 1.92 | 59 | 726 |
| bootique-deep | 4.82 | 517.80 | 511.50 | 78.20 | 69.98 | 0.42 | 42 | 1057 |
| guice-deep | 5.75 | 689.80 | 628.50 | 104.40 | 74.25 | 0.64 | 74 | 1141 |
| spring-xml-deep | 6.90 | 868.60 | 843.30 | 118.60 | 75.45 | 1.24 | 94 | 931 |
| spring-deep | 6.91 | 1,066.80 | 1,189.30 | 140.30 | 75.31 | 0.98 | 123 | 1032 |
| owb-deep | 3.42 | 1,130.60 | 1,391.70 | 147.00 | 78.70 | 1.04 | 137 | 1143 |
| spring-index-deep | 6.91 | 1,187.30 | 1,521.40 | 141.90 | 81.28 | 1.67 | 213 | 729 |
| spring-scan-deep | 6.91 | 1,361.00 | 1,719.00 | 168.00 | 81.69 | 1.68 | 218 | 728 |
| springboot-index-deep | 10.46 | 2,234.70 | 3,027.00 | 247.60 | 112.44 | 2.99 | 451 | 739 |
| springboot-deep | 10.46 | 2,558.00 | 3,515.90 | 275.90 | 115.62 | 2.91 | 464 | 1050 |
| EN | RU |
|---|---|
| README in English | README на русском |
Section DI Containers Comparison was created using:
- Project: DI Containers Comparison
- Author: Ruslan Ibrahimau (Ibragimov)
- License: Creative Commons Attribution 4.0 International (CC BY 4.0)
Created by @akardapolov
