{"id":16378169,"url":"https://github.com/a248/solidinjector","last_synced_at":"2025-10-26T10:30:44.505Z","repository":{"id":43300102,"uuid":"315741648","full_name":"A248/SolidInjector","owner":"A248","description":"Modern and lightweight injector supporting javax and jarkarta.","archived":false,"fork":false,"pushed_at":"2023-08-17T02:11:18.000Z","size":189,"stargazers_count":4,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-01-31T18:13:11.680Z","etag":null,"topics":["dependency-injection","dependency-injection-container","dependency-injection-framework","di-container","java"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"lgpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/A248.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-11-24T20:11:46.000Z","updated_at":"2022-12-27T09:46:50.000Z","dependencies_parsed_at":"2022-08-04T18:15:18.152Z","dependency_job_id":null,"html_url":"https://github.com/A248/SolidInjector","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/A248%2FSolidInjector","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/A248%2FSolidInjector/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/A248%2FSolidInjector/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/A248%2FSolidInjector/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/A248","download_url":"https://codeload.github.com/A248/SolidInjector/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":238310177,"owners_count":19450805,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dependency-injection","dependency-injection-container","dependency-injection-framework","di-container","java"],"created_at":"2024-10-11T03:44:47.142Z","updated_at":"2025-10-26T10:30:44.182Z","avatar_url":"https://github.com/A248.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n# SolidInjector [![Maven Central](https://img.shields.io/maven-central/v/space.arim.injector/injector?color=brightgreen\u0026label=maven%20central)](https://mvnrepository.com/artifact/space.arim.injector/injector) [![Javadoc](https://javadoc.io/badge2/space.arim.injector/injector/javadoc.svg)](https://javadoc.io/doc/space.arim.injector/injector)\n\nModern and lightweight injector supporting javax and jarkarta.\n\n## Introduction\n\nI was looking for an implementation of the javax.inject or jakarta.inject specification for a small project I was making. However, the ones I found were either too bulky and over-the-top, or abandoned by the author.\n\n### Features\n\n* Supports javax.inject and jakarta.inject.\n* Easy to configure.\n* Provides `module-info` while remaining Java 8 compatible.\n* Compliant with the specification.\n* Permits constructor, field, and method injection.\n\nThere are no dependencies except JDK 8, and a choice of javax.inject or jakarta.inject.\n\n### Dependency\n\nThe dependency is `space.arim.injector:injector`. It is deployed to Central.\n\nFor those using JPMS, the module name is `space.arim.injector`\n\nThough the public API is small, the javadocs may be browsed using [here](https://javadoc.io/doc/space.arim.injector/injector) or in your IDE.\n\n## Injection Usage\n\n### Basic Use\n\nConcrete classes are instantiated directly, either using the default constructor, or through the public constructor annotated with `@Inject`.\n\n```java\npublic class Plane {\n\n\tprivate final Wing wing;\n\n\t@Inject\n\tpublic Plane(Wing wing) { // Wing is automatically instantiated\n\t\tthis.wing = wing;\n\t}\n}\n\npublic class Wing {\n\t\n\t/*\n\t * Define further dependencies in constructor, fields, or methods\n\t@Inject\n\tpublic Wing(Foil someOtherDependency) {\n\t\t\n\t}\n\t*/\n\t\n\t// This class can be instantiated whether or not the constructor is commented out\n\t\n}\n```\n\nThere can be at most 1 constructor annotated with `@Inject`.\n\nTo instantiate a Plane:\n\n```java\nInjector injector = Injector.newInjector();\nPlane plane = injector.request(Plane.class);\n```\n\n### Private and Static Injection\n\nBy default, only public instance members (constructors, fields, and methods) are injected. To enable private injection, use the InjectorBuilder:\n\n```java\nInjector injector = new InjectorBuilder().privateInjection(true).build();\nPlane plane = injector.request(Plane.class);\n```\n\n* When using JPMS, private injection requires modules to be *open* to SolidInjector.\n* Static injection can also be enabled using InjectorBuilder, but static injection is highly discouraged.\n\n### Bindings\n\nAbstract classes and interfaces require bindings. This is best demonstrated with an example.\n\nTake the following `TrafficControl` interface, and an implementation `NoOpTrafficControl`:\n\n```java\npublic interface TrafficControl {\n\n\tboolean canLand(Plane plane);\n\t\n}\n\npublic class NoOpTrafficControl implements TrafficControl {\n\n\t@Override\n\tpublic boolean canLand(Plane plane) {\n\t\t// Uh-oh!\n\t\treturn true;\n\t}\n\n}\n```\n\nThis would be idiomatically bound with:\n\n```java\npublic class AirportModule {\n\n\tpublic TrafficControl trafficControl(NoOpTrafficControl trafficControl) {\n\t\treturn trafficControl;\n\t}\n\t\n}\n```\n\nYou may add as many modules to the injector as desired. Ordering is unimportant:\n\n```java\nInjector injector = Injector.newInjector(new AirportModule(), new TrainStationModule());\n\nPlane plane = injector.request(Plane.class);\nTrain train = injector.request(Train.class);\n```\n\n**Binding Method Details**\n\n* Method parameters are treated as further dependencies.\n* All public instance methods, declared and inherited, will be used.\n\n### Provider\n\njavax.inject.Provider or jakarta.inject.Provider may be used to break circular dependencies or for deferred retrieval. \n\nFor any type `T`, you can also inject `Provider\u003cT\u003e` whose get() method will return an instance of T.\n\n### Singleton\n\nPer the javax/jakarta spec:\n* Concrete classes annotated with @Singleton will be instantiated at most once.\n\nWith regards to SolidInjector:\n* Binding methods annotated with @Singleton will be called at most once.\n\n### Circular Dependencies\n\nCircular dependencies are detected, and an exception is thrown. `Provider` can be used to break circular dependencies. Alternatively, consider refactoring.\n\n### JPMS\n\njakarta.inject has an 'Automatic-Module-Name' and is therefore safe to use on the modular classpath.\n\njavax.inject is in somewhat of a predicament. The original JSR-330 does not define its module name. However, the unofficial continuation of javax.inject under Jakarta EE 8 does define `java.inject` as the module name, see [here](https://github.com/eclipse-ee4j/injection-api/issues/14). This is also the logical module name which was discussed for JSR-330.\n\nTherefore, when using javax.inject in a modular environment, use the 'java.inject' module name and the Jakarta EE 8 continuation of javax.inject\n\n### Extra Features outside the specification\n\nThese features fall outside the official specification. They must be explicitly enabled by configuring the InjectorBuilder:\n* `injectorBuilder.multiBindings(true)` for multi-binding\n* `injectorBuilder.optionalBindings(true)` for optional binding\n\n**Multiple bindings**\n\nSometimes you may want to bind multiple implementations, and inject a `Set` of such instances.\n\nTo use this feature, use `@MultiBinding` on bind methods: multiple such bind methods may exist associated to the same interface.\n\n```java\npublic class MultiBindingModule {\n\t@MultiBinding\n\tpublic MyService provider1(MyServiceImpl1 impl1) {\n\t\treturn impl1;\n\t}\n\n\t@MultiBinding\n\tpublic MyService provider2(MyServiceImpl2 impl2) {\n\t\treturn impl2;\n    }\n}\n```\n\nRequest all implementations as a `Set`, again specifying `@MultiBinding`:\n\n```java\npublic class MyDependent { \n\tprivate final Set\u003cMyService\u003e myServices;\n\n\tpublic MyDependent(@MultiBinding Set\u003cMyService\u003e myServices) {\n\t\tthis.myServices = myServices;\n\t}\n}\n```\n\nYou must use `@MultiBinding` on bind methods *and* at injection points.\n\n**Optional Bindings**\n\nAn intuitive feature. If the binding is present, the optional is present. Otherwise the optional is empty.\n\n```java\npublic class MyDependent {\n    @Inject\n    public void injectOptionalService(Optional\u003cMyService\u003e optionalService) {\n        if (optionalService.isPresent()) {\n            MyService impl = optionalService.get();\n            System.out.println(\"MyService is bound to \" + impl);\n        } else {\n            System.out.println(\"MyService is not bound\");\n        }\n    }\n}\n```\n\nFor use with `Provider`, inject a `Optional\u003cProvider\u003cT\u003e\u003e`. Note that `Provider\u003cOptional\u003e` is *not* supported.\n\n*Warning*: Do not mix Optional requests with non-optional requests for concrete classes:\n  * That is, your dependency graph should not contain both `MyConcreteClass` and `Optional\u003cMyConcreteClass\u003e` if `MyConcreteClass` is instantiable.\n  * If you do this, you subject yourself to the arbitrary and unpredictable instantiation order of your dependency graph. When `Optional\u003cMyConcreteClass` is requested, if `MyConcreteClass` was requested first, you will receive the instance. However, if `MyConcreteClass` was not previously requested, you will receive an empty optional.\n  * This happens because `MyConcreteClass` is instantiated automatically when it is requested, but optional requests do not cause automatic instantiation.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fa248%2Fsolidinjector","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fa248%2Fsolidinjector","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fa248%2Fsolidinjector/lists"}