<repositories>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>
<dependency>
<groupid>com.github.jwdeveloper.DepenDance</groupid>
<artifactid>DepenDance-Full</artifactid>
<version>0.0.20-Release</version>
</dependency> 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 ## 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.
Injecting object via constructor
Method object providers
Class Scanner to avoid manual registration Scanner
You need to get List of objects in the constructor, no problem
Create object instance by yourself and register it to container!
Object lifetimes [SINGLETON, TRANSIENT] see
Highly customizable, adjust container with build in events system
publicclass_01_Basic {
publicstaticvoidmain(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 */DependanceContainercontainer = Dependance.newContainer()
.registerTransient(Shop.class, LocalShop.class) //registration interface to implementation
.registerSingleton(Config.class)
.registerSingleton(ShopManager.class)
.build();
ShopManagershopManager1 = container.find(ShopManager.class);
ShopManagershopManager2 = container.find(ShopManager.class);
Shopshop1 = container.find(Shop.class);
Shopshop2 = 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");
}
} publicclass_02_Object_Instances
{
publicstaticvoidmain(String[] args)
{
ConfigmyConfigInstance = newConfig();
DependanceContainercontainer = 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 outputvarconfig = (Config)di.find(Config.class);
varshop = newLocalShop(config);
System.out.println("Shop has been created: "+shop);
returnshop;
})
.build();
Configconfig = container.find(Config.class);
LocalShopshop1 = container.find(LocalShop.class);
LocalShopshop2 = 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");
}
} publicclass_03_Lists {
publicstaticvoidmain(String[] args) {
DependanceContainercontainer = Dependance.newContainer()
.registerSingleton(Config.class)
.registerTransient(Shop.class, OnlineShop.class)
.registerTransient(Shop.class, LocalShop.class)
.registerTransientList(Shop.class)
.build();
List<Shop> shops = (List<Shop>) container.find(List.class, Shop.class);
for (varshop : shops) {
System.out.println("Shops: " + shop.getClass().getSimpleName());
}
Assert.assertEquals(2, shops.size());
}
} publicclass_04_Events {
publicstaticvoidmain(String[] args) {
DependanceContainercontainer = 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();
Objectshops = container.find(Shop.class, String.class);
}
privatestaticBooleanonRegistration(OnRegistrationEventevent) {
System.out.println("onRegistration event: " + event.registrationInfo().implementation().getSimpleName());
returntrue; //If false `container.find` injection is not registered to container
}
privatestaticObjectonInjection(OnInjectionEventevent) {
varinputType = event.input();// searched class type provided as first parametersvargenericTypes = event.inputGenericParameters(); //list of generic types provided as second parametervaroutputObject = event.output(); //Target object instance type has not been found then output value is nullvarcontainer = event.container(); //access to DI containervarinjectonMetadata = 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());
returnoutputObject;
}
} publicclass_05_Generic_Types {
publicstaticvoidmain(String[] args) {
varcontainer = 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<MyGenericType>.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)) {
returninjection.output();
}
vargenericParameter = injection.inputGenericParameters()[0];
if (genericParameter.equals(OnlineShop.class)) {
returnnewRepository<OnlineShop>();
}
if (genericParameter.equals(LocalShop.class)) {
returnnewRepository<LocalShop>();
}
returnnewRepository();
});
})
.build();
//first parameter is class, second one is its generic parametervarexampleGenericsTypes = container.find(ExampleGenericsTypes.class);
Assert.assertNotNull(exampleGenericsTypes);
Assert.assertNotNull(exampleGenericsTypes.getLocalShopRepository());
Assert.assertNotNull(exampleGenericsTypes.getOnlineShopRepository());
}
publicstaticclassExampleGenericsTypes {
@GetterprivateRepository<OnlineShop> onlineShopRepository;
@GetterprivateRepository<LocalShop> localShopRepository;
publicExampleGenericsTypes(Repository<OnlineShop> onlineShopRepository,
Repository<LocalShop> localShopRepository) {
this.onlineShopRepository = onlineShopRepository;
this.localShopRepository = localShopRepository;
}
}
} publicclass_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 */publicstaticvoidmain(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;
DependanceContainercontainer = 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 (varclazz : scannedClasses)
{
System.out.println(clazz.getSimpleName());
}
System.out.println("============================================");
})
.build();
Configconfig = container.find(Config.class);
ExampleClassexampleClass = container.find(ExampleClass.class);
OnlineShoponlineShop = container.find(OnlineShop.class);
ExampleScannClassexampleScannClass = container.find(ExampleScannClass.class);
Assert.assertNotNull(config);
Assert.assertNotNull(exampleClass);
Assert.assertNotNull(onlineShop);
Assert.assertNotNull(exampleScannClass);
}
/** * This is equivalent of * <p> * container.registerTransient(OnlineShop.class,container1 -> * { * System.out.println("Hello from the online shop factory"); * return new OnlineShop(); * }) */@Injection(lifeTime = LifeTime.TRANSIENT)
privatestaticOnlineShoponlineShopFactory() {
System.out.println("Hello from the online shop factory");
returnnewOnlineShop();
}
/** * This is equivalent of * <p> * container.registerSingleton(ExampleScannClass.class); */@Injection(lifeTime = LifeTime.SINGLETON)
publicstaticclassExampleScannClass {
publicExampleScannClass() {
System.out.println("Hello world!");
}
}
} publicclass_07_Overriding {
publicstaticvoidmain(String[] args) {
DependanceContainercontainer = 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();
Shopshop = container.find(Shop.class);
Assert.assertEquals(OfflineShop.class, shop.getClass());
System.out.println("shop object is instance of OfflineShop Class");
}
} publicclass_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 * */publicstaticvoidmain(String[] args) {
DependanceContainercontainer = Dependance.newContainer()
.registerTransient(ExampleClass.class)
.registerTransient(ManyConstructorsExample.class)
.build();
ManyConstructorsExampleexample = container.find(ManyConstructorsExample.class);
Assert.assertNotNull(example);
System.out.println("It works!");
}
publicstaticclassManyConstructorsExample
{
publicManyConstructorsExample(Stringa, intb, booleanc)
{
}
@InjectpublicManyConstructorsExample(ExampleClassc)
{
System.out.println("Hello from constructor with ExampleClass parameter");
}
}
publicstaticclassExampleClass
{
}
} publicclass_09_Fields {
publicstaticvoidmain(String[] args) {
DependanceContainercontainer = Dependance.newContainer()
.registerTransient(_09_Fields.ExampleSerivce.class)
.registerTransient(_09_Fields.ExampleClass.class)
.build();
_09_Fields.ExampleSerivceexample = container.find(_09_Fields.ExampleSerivce.class);
Assert.assertNotNull(example);
example.exampleClass.sayIt();
}
publicstaticclassExampleSerivce {
@InjectExampleClassexampleClass;
}
publicstaticclassExampleClass {
publicvoidsayIt() {
System.out.println("Hello world!");
}
}
} publicclass_10_Methods
{
publicstaticvoidmain(String[] args) {
DependanceContainercontainer = Dependance.newContainer()
.registerTransient(_10_Methods.ExampleSerivce.class)
.registerTransient(_10_Methods.ExampleClass.class)
.build();
_10_Methods.ExampleClassexample = container.find(_10_Methods.ExampleClass.class);
Assert.assertNotNull(example);
example.sayIt();
}
publicstaticclassExampleSerivce
{
@Injection_09_Fields.ExampleClassexampleClassProvider()
{
returnnew_09_Fields.ExampleClass();
}
}
publicstaticclassExampleClass {
publicvoidsayIt() {
System.out.println("Hello world!");
}
}
} publicclass_11_ResolveParameters {
publicstaticvoidmain(String[] args) throwsException {
DependanceContainercontainer = Dependance.newContainer()
.registerTransient(_11_ResolveParameters.ExampleWithGenerics.class)
.registerTransient(_11_ResolveParameters.ExampleClass.class)
.configure(config ->
{
config.onInjection(onInjectionEvent ->
{
if (!onInjectionEvent.input().equals(ExampleWithGenerics.class)) {
returnonInjectionEvent.output();
}
vargeneicsTyles = onInjectionEvent.inputGenericParameters()[0];
if (!String.class.equals(geneicsTyles)) {
returnonInjectionEvent.output();
}
returnnewExampleWithGenerics<String>();
});
})
.build();
varmethod = _11_ResolveParameters.class.getDeclaredMethod(
"sayHello",
_11_ResolveParameters.ExampleWithGenerics.class,
_11_ResolveParameters.ExampleClass.class);
varparameters = container.resolveParameters(method);
method.invoke(null, parameters);
}
publicstaticvoidsayHello(_11_ResolveParameters.ExampleWithGenerics<String> exampleService,
_11_ResolveParameters.ExampleClassexampleClass) {
System.out.println("Hello world");
}
publicstaticclassExampleWithGenerics<T> {
}
publicstaticclassExampleClass {
}
}