Refractor Dependency Injector -> Add public methods for developper's usage, optimise searching by using correctly the cache, add toString() method for debugs
This commit is contained in:
parent
2cf4363e25
commit
c06cc46787
3 changed files with 34 additions and 29 deletions
|
@ -1,6 +1,7 @@
|
|||
package dev.peerat.framework;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Executable;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Parameter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
@ -11,14 +12,13 @@ import java.util.function.BiFunction;
|
|||
public class DependencyInjector{
|
||||
|
||||
private Map<String, Object> map;
|
||||
private List<BiFunction<Constructor<?>, Parameter, Object>> builders;
|
||||
private List<BiFunction<Injection, Class<?>, Object>> builders;
|
||||
private Object[] injections;
|
||||
private Map<Class<?>, Object> cache;
|
||||
|
||||
public DependencyInjector(){
|
||||
this.map = new HashMap<>();
|
||||
this.builders = new ArrayList<>();
|
||||
this.cache = new HashMap<>();
|
||||
}
|
||||
|
||||
public DependencyInjector of(String name, Object value){
|
||||
|
@ -26,7 +26,7 @@ public class DependencyInjector{
|
|||
return this;
|
||||
}
|
||||
|
||||
public DependencyInjector of(BiFunction<Constructor<?>, Parameter, Object> builder){
|
||||
public DependencyInjector of(BiFunction<Injection, Class<?>, Object> builder){
|
||||
this.builders.add(builder);
|
||||
return this;
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ public class DependencyInjector{
|
|||
public DependencyInjector of(Object... injections){
|
||||
if(this.injections == null){
|
||||
this.injections = injections;
|
||||
this.cache = new HashMap<>();
|
||||
return this;
|
||||
}
|
||||
Object[] copy = new Object[this.injections.length+injections.length];
|
||||
|
@ -43,31 +44,43 @@ public class DependencyInjector{
|
|||
return this;
|
||||
}
|
||||
|
||||
Object applyDependency(Constructor<?> constructor, Parameter parameter){
|
||||
Injection annotation = parameter.getAnnotation(Injection.class);
|
||||
public Object[] apply(Executable executable) throws Exception{
|
||||
Parameter[] parameters = executable.getParameters();
|
||||
Object[] injections = new Object[parameters.length];
|
||||
for(int i = 0; i < parameters.length; i++) injections[i] = find(parameters[i].getAnnotation(Injection.class), parameters[i].getType());
|
||||
return injections;
|
||||
}
|
||||
|
||||
public Object apply(Field field) throws Exception{
|
||||
return find(field.getAnnotation(Injection.class), field.getType());
|
||||
}
|
||||
|
||||
public Object find(Injection annotation, Class<?> type){
|
||||
if(annotation != null){
|
||||
Object result = this.map.get(annotation.value());
|
||||
if(result == null) throw new IllegalArgumentException("No depdency named "+annotation.value()+" ("+this.map.keySet()+") in constructor "+constructor);
|
||||
if(result == null) throw new IllegalArgumentException("No depdency named "+annotation.value()+" ("+this.map.keySet()+")");
|
||||
return result;
|
||||
}
|
||||
for(BiFunction<Constructor<?>, Parameter, Object> function : builders){
|
||||
Object result = function.apply(constructor, parameter);
|
||||
for(BiFunction<Injection, Class<?>, Object> function : builders){
|
||||
Object result = function.apply(annotation, type);
|
||||
if(result != null) return result;
|
||||
}
|
||||
Class<?> type = parameter.getType();
|
||||
if(this.injections == null) throw new IllegalArgumentException("No dependency for type "+type+" in constructor "+constructor);
|
||||
Object result = null;
|
||||
if(this.injections == null) throw new IllegalArgumentException("No dependency for type "+type);
|
||||
Object result = this.cache.get(type);
|
||||
if(result != null) return result;
|
||||
for(Object injection : injections){
|
||||
if(type.isAssignableFrom(injection.getClass())){
|
||||
if(cache.containsKey(type)){
|
||||
throw new IllegalArgumentException("Double dependency for type "+type+", can be in constructor "+constructor);
|
||||
}else{
|
||||
cache.put(type, injection);
|
||||
result = injection;
|
||||
}
|
||||
if(cache.containsKey(type)) throw new IllegalArgumentException("Double dependency for type "+type);
|
||||
cache.put(type, injection);
|
||||
result = injection;
|
||||
}
|
||||
}
|
||||
if(result == null) throw new IllegalArgumentException("No dependency for type "+type+" in constructor "+constructor);
|
||||
if(result == null) throw new IllegalArgumentException("No dependency for type "+type);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(){
|
||||
return "([DependencyInjector] map="+map+",buildersCount="+builders.size()+",injections="+injections+",cache="+cache+")";
|
||||
}
|
||||
}
|
|
@ -4,7 +4,6 @@ import java.lang.reflect.Method;
|
|||
import java.security.MessageDigest;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import dev.peerat.framework.utils.json.JsonMap;
|
||||
|
||||
|
|
|
@ -119,7 +119,7 @@ public class Router<U extends User>{
|
|||
public Router<U> registerClass(Class<?> clazz, DependencyInjector injector) throws Exception{
|
||||
Constructor<?>[] constructors = clazz.getDeclaredConstructors();
|
||||
if(constructors.length != 1) throw new IllegalArgumentException("Class with multiple constructor. Not supported by this framework for the moment.");
|
||||
Object instance = injectDependencies(constructors[0], injector);
|
||||
Object instance = constructors[0].newInstance(injector.apply(constructors[0]));
|
||||
|
||||
for(Method method : clazz.getDeclaredMethods()){
|
||||
Route route = method.getAnnotation(Route.class);
|
||||
|
@ -167,13 +167,6 @@ public class Router<U extends User>{
|
|||
return this;
|
||||
}
|
||||
|
||||
private Object injectDependencies(Constructor<?> constructor, DependencyInjector injector) throws Exception{
|
||||
Parameter[] parameters = constructor.getParameters();
|
||||
Object[] injections = new Object[parameters.length];
|
||||
for(int i = 0; i < parameters.length; i++) injections[i] = injector.applyDependency(constructor, parameters[i]);
|
||||
return constructor.newInstance(injections);
|
||||
}
|
||||
|
||||
public Router<U> setDefault(Response response){
|
||||
this.noFileFound = response;
|
||||
return this;
|
||||
|
|
Loading…
Add table
Reference in a new issue