An open API service indexing awesome lists of open source software.

https://github.com/jwdeveloper/dependance

Simple and easy to use dependecy injection container for Java
https://github.com/jwdeveloper/dependance

containers dependance dependecy-container dependecy-injection dependecy-injection-container di dic java

Last synced: 10 months ago
JSON representation

Simple and easy to use dependecy injection container for Java

Awesome Lists containing this project

README

          

DepenDance

*💉 Inject Simplicity, Eject Complexity 🪲*

```xml



jitpack.io
https://jitpack.io



com.github.jwdeveloper.DepenDance
DepenDance-Full
0.0.20-Release

```

Depandance is the dependency injection container library. Is is quite compacts and has a lot of features you can find in the more popular DI container libraries. ## What are the dependecies? Dependecies is the fancy word for a class consturctor parameters. So the objects certain class depends on/ ## What is the dependecy injection? Is is one of the programming design patters, watch great video about it [Video](https://www.youtube.com/watch?v=J1f5b4vcxCQ) ## What is the dependecy injection container? It is library that helps to create instance of object with all its `dependecines`. At the beggining you need to register the dependecines classess to the container, then any class that was registed, can be obtained for the container.

Features

- [x] Injecting object via constructor

- [x] Method object providers

- [x] Class Scanner to avoid manual registration [Scanner](#autoscan)

- [x] You need to get [List of objects](#lists) in the constructor, no problem

- [x] Create [object instance](#object-instances) by yourself and register it to container!

- [x] Object lifetimes [SINGLETON, TRANSIENT] [see](#basic)

- [x] [Generic types](#generic-types)

- [x] [Many constructors](#manyconstructors)

- [x] Highly customizable, adjust container with build in [events](#events) system

Tutorial

[01 Basic](https://github.com/jwdeveloper/DepenDance?tab=readme-ov-file#01-Basic)

[02 Object Instances](https://github.com/jwdeveloper/DepenDance?tab=readme-ov-file#02-Object-Instances)

[03 Lists](https://github.com/jwdeveloper/DepenDance?tab=readme-ov-file#03-Lists)

[04 Events](https://github.com/jwdeveloper/DepenDance?tab=readme-ov-file#04-Events)

[05 Generic Types](https://github.com/jwdeveloper/DepenDance?tab=readme-ov-file#05-Generic-Types)

[06 AutoScan](https://github.com/jwdeveloper/DepenDance?tab=readme-ov-file#06-AutoScan)

[07 Overriding](https://github.com/jwdeveloper/DepenDance?tab=readme-ov-file#07-Overriding)

[08 ManyConstructors](https://github.com/jwdeveloper/DepenDance?tab=readme-ov-file#08-ManyConstructors)

[09 Fields](https://github.com/jwdeveloper/DepenDance?tab=readme-ov-file#09-Fields)

[10 Methods](https://github.com/jwdeveloper/DepenDance?tab=readme-ov-file#10-Methods)

[11 ResolveParameters](https://github.com/jwdeveloper/DepenDance?tab=readme-ov-file#11-ResolveParameters)

### 01 Basic

```java
public class _01_Basic {

public static void main(String[] args) {
/*
- Singleton There will be only one instance of object created by container
- Transient everytime `container.find` is used new instance of object is created
*/

DependanceContainer container = Dependance.newContainer()
.registerTransient(Shop.class, LocalShop.class) //registration interface to implementation
.registerSingleton(Config.class)
.registerSingleton(ShopManager.class)
.build();

ShopManager shopManager1 = container.find(ShopManager.class);
ShopManager shopManager2 = container.find(ShopManager.class);

Shop shop1 = container.find(Shop.class);
Shop shop2 = container.find(Shop.class);

Assert.assertEquals(shopManager1, shopManager2);
System.out.println("There always same instance of shop manager");

Assert.assertEquals(shopManager1.getConfig(), shopManager2.getConfig());
System.out.println("There always same instance of config");

Assert.assertNotEquals(shop1, shop2);
System.out.println("There are different instances of shop");
}
}
```
### 02 Object Instances

```java
public class _02_Object_Instances
{
public static void main(String[] args)
{
Config myConfigInstance = new Config();
DependanceContainer container = Dependance.newContainer()
.registerSingleton(Config.class, myConfigInstance) //in case we want to make instance manually we can put object as second argument
.registerTransient(LocalShop.class,(di)->
{
//more complex case, we want to find or put manually arguments to created instance
//for that we can use lamda resolver that has container as input, and object instance as output
var config = (Config)di.find(Config.class);
var shop = new LocalShop(config);
System.out.println("Shop has been created: "+shop);
return shop;
})
.build();

Config config = container.find(Config.class);
LocalShop shop1 = container.find(LocalShop.class);
LocalShop shop2 = container.find(LocalShop.class);

Assert.assertEquals(myConfigInstance,config);
System.out.println("Config has same instance");

Assert.assertNotEquals(shop1,shop2);
System.out.println("Shops has different instances");
}
}
```
### 03 Lists

```java
public class _03_Lists {
public static void main(String[] args) {
DependanceContainer container = Dependance.newContainer()
.registerSingleton(Config.class)
.registerTransient(Shop.class, OnlineShop.class)
.registerTransient(Shop.class, LocalShop.class)
.registerTransientList(Shop.class)
.build();

List shops = (List) container.find(List.class, Shop.class);

for (var shop : shops) {
System.out.println("Shops: " + shop.getClass().getSimpleName());
}
Assert.assertEquals(2, shops.size());
}

}
```
### 04 Events

```java
public class _04_Events {
public static void main(String[] args) {
DependanceContainer container = Dependance.newContainer()
.registerSingleton(Shop.class, LocalShop.class)
.registerSingleton(Shop.class, OnlineShop.class)
.configure(config ->
{
config.onInjection(_04_Events::onInjection);
config.onRegistration(_04_Events::onRegistration);
})
.build();

Object shops = container.find(Shop.class, String.class);
}

private static Boolean onRegistration(OnRegistrationEvent event) {
System.out.println("onRegistration event: " + event.registrationInfo().implementation().getSimpleName());
return true; //If false `container.find` injection is not registered to container
}

private static Object onInjection(OnInjectionEvent event) {
var inputType = event.input();// searched class type provided as first parameters
var genericTypes = event.inputGenericParameters(); //list of generic types provided as second parameter
var outputObject = event.output(); //Target object instance type has not been found then output value is null
var container = event.container(); //access to DI container
var injectonMetadata = event.injectionInfo();

System.out.println("OnInjection input class: " + inputType.getSimpleName());
System.out.println("OnInjection output class: " + outputObject.getClass().getSimpleName());
System.out.println("OnInjection genericTypes: " + genericTypes.length);
System.out.println("OnInjection metadata: " + injectonMetadata.toString());
return outputObject;
}
}
```
### 05 Generic Types

```java
public class _05_Generic_Types {

public static void main(String[] args) {

var container = Dependance.newContainer()
.registerTransient(ExampleGenericsTypes.class)
.configure(configuration ->
{
/*
* Since java is not storing information about generic type after compilation
* we can not assign class with generic type to variable, so Repository.class is not possible
* Therefor all cases with generic types (besides lists) must be handled manually in onInjection event
*/

configuration.onInjection(injection ->
{
if (!injection.input().isAssignableFrom(Repository.class)) {
return injection.output();
}

var genericParameter = injection.inputGenericParameters()[0];
if (genericParameter.equals(OnlineShop.class)) {
return new Repository();
}
if (genericParameter.equals(LocalShop.class)) {
return new Repository();
}
return new Repository();
});
})

.build();

//first parameter is class, second one is its generic parameter
var exampleGenericsTypes = container.find(ExampleGenericsTypes.class);

Assert.assertNotNull(exampleGenericsTypes);
Assert.assertNotNull(exampleGenericsTypes.getLocalShopRepository());
Assert.assertNotNull(exampleGenericsTypes.getOnlineShopRepository());

}

public static class ExampleGenericsTypes {

@Getter
private Repository onlineShopRepository;
@Getter
private Repository localShopRepository;

public ExampleGenericsTypes(Repository onlineShopRepository,
Repository localShopRepository) {
this.onlineShopRepository = onlineShopRepository;
this.localShopRepository = localShopRepository;
}
}

}
```
### 06 AutoScan

```java
public class _06_AutoScan {

/**
* To avoid boring manually registering Types to container
* use `scan` method that is looking for all Classes and Methods
* with annotation @Injection and register it automatically
*/

public static void main(String[] args) {

/*
* package under which code will be scanned should be scanned
* scanner is looking for all Method and Classes that are having @Injection annotation
*/

Class> rootClass = _06_AutoScan.class;

DependanceContainer container = Dependance.newContainer()
.scan(rootClass)
.scan(options ->
{
options.setRootPackage(rootClass);
options.excludeClass("org.example.ExampleClass");
options.excludePackage(String.class.getPackageName());
})
.scan(rootClass, (scannedClasses, containerBuilder) ->
{
System.out.println("Hello from scanner those are found classes");
for (var clazz : scannedClasses)
{
System.out.println(clazz.getSimpleName());
}
System.out.println("============================================");
})
.build();

Config config = container.find(Config.class);
ExampleClass exampleClass = container.find(ExampleClass.class);
OnlineShop onlineShop = container.find(OnlineShop.class);
ExampleScannClass exampleScannClass = container.find(ExampleScannClass.class);

Assert.assertNotNull(config);
Assert.assertNotNull(exampleClass);
Assert.assertNotNull(onlineShop);
Assert.assertNotNull(exampleScannClass);
}

/**
* This is equivalent of
*


* container.registerTransient(OnlineShop.class,container1 ->
* {
* System.out.println("Hello from the online shop factory");
* return new OnlineShop();
* })
*/
@Injection(lifeTime = LifeTime.TRANSIENT)
private static OnlineShop onlineShopFactory() {
System.out.println("Hello from the online shop factory");
return new OnlineShop();
}

/**
* This is equivalent of
*


* container.registerSingleton(ExampleScannClass.class);
*/
@Injection(lifeTime = LifeTime.SINGLETON)
public static class ExampleScannClass {
public ExampleScannClass() {
System.out.println("Hello world!");
}
}
}
```
### 07 Overriding

```java
public class _07_Overriding {
public static void main(String[] args) {

DependanceContainer container = Dependance.newContainer()
.registerTransient(Shop.class, OnlineShop.class)
.registerTransient(Shop.class, OfflineShop.class)
/**
* By again declaring Shop but with different implementation (OnlineShop)
* We are telling container to Override (OfflineShop) and always returns (OnlineShop)
*/
.build();

Shop shop = container.find(Shop.class);
Assert.assertEquals(OfflineShop.class, shop.getClass());
System.out.println("shop object is instance of OfflineShop Class");
}
}
```
### 08 ManyConstructors

```java
public class _08_ManyConstructors
{
/**
* By the default the first constructor is always targeted for injecting parameters
* However, sometimes class can have more than one constructor, or we want to use
* specific one.
*
* To do that use @Inject annotation over wanted constructor
*
*/

public static void main(String[] args) {

DependanceContainer container = Dependance.newContainer()
.registerTransient(ExampleClass.class)
.registerTransient(ManyConstructorsExample.class)
.build();

ManyConstructorsExample example = container.find(ManyConstructorsExample.class);
Assert.assertNotNull(example);
System.out.println("It works!");
}

public static class ManyConstructorsExample
{

public ManyConstructorsExample(String a, int b, boolean c)
{

}

@Inject
public ManyConstructorsExample(ExampleClass c)
{
System.out.println("Hello from constructor with ExampleClass parameter");
}
}

public static class ExampleClass
{

}
}
```
### 09 Fields

```java
public class _09_Fields {

public static void main(String[] args) {
DependanceContainer container = Dependance.newContainer()
.registerTransient(_09_Fields.ExampleSerivce.class)
.registerTransient(_09_Fields.ExampleClass.class)
.build();

_09_Fields.ExampleSerivce example = container.find(_09_Fields.ExampleSerivce.class);
Assert.assertNotNull(example);
example.exampleClass.sayIt();
}

public static class ExampleSerivce {
@Inject
ExampleClass exampleClass;
}

public static class ExampleClass {
public void sayIt() {
System.out.println("Hello world!");
}
}
}
```
### 10 Methods

```java
public class _10_Methods
{
public static void main(String[] args) {
DependanceContainer container = Dependance.newContainer()
.registerTransient(_10_Methods.ExampleSerivce.class)
.registerTransient(_10_Methods.ExampleClass.class)
.build();

_10_Methods.ExampleClass example = container.find(_10_Methods.ExampleClass.class);
Assert.assertNotNull(example);
example.sayIt();
}

public static class ExampleSerivce
{
@Injection
_09_Fields.ExampleClass exampleClassProvider()
{
return new _09_Fields.ExampleClass();
}
}

public static class ExampleClass {
public void sayIt() {
System.out.println("Hello world!");
}
}
}
```
### 11 ResolveParameters

```java
public class _11_ResolveParameters {
public static void main(String[] args) throws Exception {
DependanceContainer container = Dependance.newContainer()
.registerTransient(_11_ResolveParameters.ExampleWithGenerics.class)
.registerTransient(_11_ResolveParameters.ExampleClass.class)
.configure(config ->
{
config.onInjection(onInjectionEvent ->
{
if (!onInjectionEvent.input().equals(ExampleWithGenerics.class)) {
return onInjectionEvent.output();
}

var geneicsTyles = onInjectionEvent.inputGenericParameters()[0];
if (!String.class.equals(geneicsTyles)) {
return onInjectionEvent.output();
}
return new ExampleWithGenerics();
});
})
.build();

var method = _11_ResolveParameters.class.getDeclaredMethod(
"sayHello",
_11_ResolveParameters.ExampleWithGenerics.class,
_11_ResolveParameters.ExampleClass.class);

var parameters = container.resolveParameters(method);

method.invoke(null, parameters);
}

public static void sayHello(_11_ResolveParameters.ExampleWithGenerics exampleService,
_11_ResolveParameters.ExampleClass exampleClass) {

System.out.println("Hello world");
}

public static class ExampleWithGenerics {

}

public static class ExampleClass {

}
}
```