From b1575e5b5211a94c8acf57b07ac9c13c864ada51 Mon Sep 17 00:00:00 2001 From: jeffcheasey88 <66554203+jeffcheasey88@users.noreply.github.com> Date: Fri, 28 Jun 2024 21:01:15 +0200 Subject: [PATCH] Update Dependencies Injections | Add possibility to give differente object's instance for the same object's type --- .../peerat/framework/DependencyInjector.java | 66 +++++++++++++++++++ src/dev/peerat/framework/Injection.java | 7 ++ src/dev/peerat/framework/Router.java | 47 +++++++------ 3 files changed, 95 insertions(+), 25 deletions(-) create mode 100644 src/dev/peerat/framework/DependencyInjector.java create mode 100644 src/dev/peerat/framework/Injection.java diff --git a/src/dev/peerat/framework/DependencyInjector.java b/src/dev/peerat/framework/DependencyInjector.java new file mode 100644 index 0000000..cf6abbc --- /dev/null +++ b/src/dev/peerat/framework/DependencyInjector.java @@ -0,0 +1,66 @@ +package dev.peerat.framework; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Parameter; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.BiFunction; + +public class DependencyInjector{ + + private Map map; + private List, Parameter, Object>> builders; + private Object[] injections; + + public DependencyInjector(){ + this.map = new HashMap<>(); + this.builders = new ArrayList<>(); + } + + public DependencyInjector of(String name, Object value){ + this.map.put(name, value); + return this; + } + + public DependencyInjector of(BiFunction, Parameter, Object> builder){ + this.builders.add(builder); + return this; + } + + public DependencyInjector of(Object... injections){ + if(this.injections == null){ + this.injections = injections; + return this; + } + Object[] copy = new Object[this.injections.length+injections.length]; + System.arraycopy(this.injections, 0, copy, 0, this.injections.length); + System.arraycopy(injections, 0, copy, this.injections.length, injections.length); + this.injections = copy; + return this; + } + + Object applyDependency(Constructor constructor, Parameter parameter, Map, Object> cache){ + Injection annotation = parameter.getAnnotation(Injection.class); + if(annotation != null) return this.map.get(annotation.name()); + for(BiFunction, Parameter, Object> function : builders){ + Object result = function.apply(constructor, parameter); + if(result != null) return result; + } + if(this.injections == null) return null; + Class type = parameter.getType(); + Object result = null; + for(Object injection : injections){ + if(type.isAssignableFrom(injection.getClass())){ + if(cache.containsKey(type)){ + throw new IllegalArgumentException("Double dependency for type "+type); + }else{ + cache.put(type, injection); + result = injection; + } + } + } + return result; + } +} diff --git a/src/dev/peerat/framework/Injection.java b/src/dev/peerat/framework/Injection.java new file mode 100644 index 0000000..eb96257 --- /dev/null +++ b/src/dev/peerat/framework/Injection.java @@ -0,0 +1,7 @@ +package dev.peerat.framework; + +public @interface Injection{ + + String name(); + +} diff --git a/src/dev/peerat/framework/Router.java b/src/dev/peerat/framework/Router.java index fd0d1d1..a9be239 100644 --- a/src/dev/peerat/framework/Router.java +++ b/src/dev/peerat/framework/Router.java @@ -6,6 +6,7 @@ import java.io.InputStreamReader; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.lang.reflect.Parameter; import java.net.ServerSocket; import java.net.Socket; import java.security.Key; @@ -111,17 +112,25 @@ public class Router{ } public Router registerPackages(Object... injections){ + return registerPackages(new DependencyInjector().of(injections)); + } + + public Router registerPackages(DependencyInjector injector){ String clazz = Thread.currentThread().getStackTrace()[2].getClassName(); String pack = clazz.substring(0, clazz.lastIndexOf('.')); - return registerPackages(pack, injections); + return registerPackages(pack, injector); } public Router registerPackages(String name, Object... injections){ + return registerPackages(name, new DependencyInjector().of(injections)); + } + + public Router registerPackages(String name, DependencyInjector injector){ InputStream stream = ClassLoader.getSystemClassLoader().getResourceAsStream(name.replace(".", "/")); try{ BufferedReader reader = new BufferedReader(new InputStreamReader(stream)); String line; - Map, Object> cache = new HashMap<>(); + Map, Object> cache = new HashMap<>(); while((line = reader.readLine()) != null){ if(line.endsWith(".class")){ Class clazz = Class.forName(name+"."+line.substring(0, line.lastIndexOf('.'))); @@ -129,10 +138,10 @@ public class Router{ if(clazz.equals(Response.class)) continue; Constructor[] constructors = clazz.getDeclaredConstructors(); if(constructors.length != 1) continue; - injectDependencies(constructors[0], cache, injections); + injectDependencies(constructors[0], cache, injector); } }else{ - registerPackages(name+"."+line); + registerPackages(name+"."+line, injector); } } reader.close(); @@ -142,30 +151,18 @@ public class Router{ return this; } - private void injectDependencies(Constructor constructor, Map, Object> cache, Object... injections){ - Class[] parameterTypes = constructor.getParameterTypes(); - Object[] parameters = new Object[parameterTypes.length]; - for(int i = 0; i < parameterTypes.length; i++){ - Class type = parameterTypes[i]; + private void injectDependencies(Constructor constructor, Map, Object> cache, DependencyInjector injector){ + Parameter[] parameters = constructor.getParameters(); + Object[] injections = new Object[parameters.length]; + for(int i = 0; i < parameters.length; i++){ + Parameter parameter = parameters[i]; + Class type = parameter.getType(); Object dependency = cache.get(type); - if(dependency != null){ - parameters[i] = dependency; - }else{ - for(Object injection : injections){ - if(type.isAssignableFrom(injection.getClass())){ - if(cache.containsKey(type)){ - throw new IllegalArgumentException("Double dependency for type "+type); - }else{ - cache.put(type, injection); - parameters[i] = injection; - } - } - } - if(parameters[i] == null) throw new IllegalArgumentException("No dependency for type "+type); - } + if(dependency != null) injections[i] = dependency; + else if((injections[i] = injector.applyDependency(constructor, parameter, cache)) == null) throw new IllegalArgumentException("No dependency for type "+type); } try { - Response response = (Response) constructor.newInstance(parameters); + Response response = (Response) constructor.newInstance(injections); register(response); System.out.println("registerd "+response.getClass()); } catch (Exception e){