Update Dependencies Injections | Add possibility to give differente object's instance for the same object's type
This commit is contained in:
parent
2c9897a7c5
commit
b1575e5b52
3 changed files with 95 additions and 25 deletions
66
src/dev/peerat/framework/DependencyInjector.java
Normal file
66
src/dev/peerat/framework/DependencyInjector.java
Normal file
|
@ -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<String, Object> map;
|
||||||
|
private List<BiFunction<Constructor<?>, 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<Constructor<?>, 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<Class<?>, Object> cache){
|
||||||
|
Injection annotation = parameter.getAnnotation(Injection.class);
|
||||||
|
if(annotation != null) return this.map.get(annotation.name());
|
||||||
|
for(BiFunction<Constructor<?>, 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;
|
||||||
|
}
|
||||||
|
}
|
7
src/dev/peerat/framework/Injection.java
Normal file
7
src/dev/peerat/framework/Injection.java
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
package dev.peerat.framework;
|
||||||
|
|
||||||
|
public @interface Injection{
|
||||||
|
|
||||||
|
String name();
|
||||||
|
|
||||||
|
}
|
|
@ -6,6 +6,7 @@ import java.io.InputStreamReader;
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
import java.lang.reflect.Parameter;
|
||||||
import java.net.ServerSocket;
|
import java.net.ServerSocket;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
import java.security.Key;
|
import java.security.Key;
|
||||||
|
@ -111,17 +112,25 @@ public class Router<U extends User>{
|
||||||
}
|
}
|
||||||
|
|
||||||
public Router<U> registerPackages(Object... injections){
|
public Router<U> registerPackages(Object... injections){
|
||||||
|
return registerPackages(new DependencyInjector().of(injections));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Router<U> registerPackages(DependencyInjector injector){
|
||||||
String clazz = Thread.currentThread().getStackTrace()[2].getClassName();
|
String clazz = Thread.currentThread().getStackTrace()[2].getClassName();
|
||||||
String pack = clazz.substring(0, clazz.lastIndexOf('.'));
|
String pack = clazz.substring(0, clazz.lastIndexOf('.'));
|
||||||
return registerPackages(pack, injections);
|
return registerPackages(pack, injector);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Router<U> registerPackages(String name, Object... injections){
|
public Router<U> registerPackages(String name, Object... injections){
|
||||||
|
return registerPackages(name, new DependencyInjector().of(injections));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Router<U> registerPackages(String name, DependencyInjector injector){
|
||||||
InputStream stream = ClassLoader.getSystemClassLoader().getResourceAsStream(name.replace(".", "/"));
|
InputStream stream = ClassLoader.getSystemClassLoader().getResourceAsStream(name.replace(".", "/"));
|
||||||
try{
|
try{
|
||||||
BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
|
BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
|
||||||
String line;
|
String line;
|
||||||
Map<Class<?>, Object> cache = new HashMap<>();
|
Map<Class<?>, Object> cache = new HashMap<>();
|
||||||
while((line = reader.readLine()) != null){
|
while((line = reader.readLine()) != null){
|
||||||
if(line.endsWith(".class")){
|
if(line.endsWith(".class")){
|
||||||
Class<?> clazz = Class.forName(name+"."+line.substring(0, line.lastIndexOf('.')));
|
Class<?> clazz = Class.forName(name+"."+line.substring(0, line.lastIndexOf('.')));
|
||||||
|
@ -129,10 +138,10 @@ public class Router<U extends User>{
|
||||||
if(clazz.equals(Response.class)) continue;
|
if(clazz.equals(Response.class)) continue;
|
||||||
Constructor<?>[] constructors = clazz.getDeclaredConstructors();
|
Constructor<?>[] constructors = clazz.getDeclaredConstructors();
|
||||||
if(constructors.length != 1) continue;
|
if(constructors.length != 1) continue;
|
||||||
injectDependencies(constructors[0], cache, injections);
|
injectDependencies(constructors[0], cache, injector);
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
registerPackages(name+"."+line);
|
registerPackages(name+"."+line, injector);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
reader.close();
|
reader.close();
|
||||||
|
@ -142,30 +151,18 @@ public class Router<U extends User>{
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void injectDependencies(Constructor<?> constructor, Map<Class<?>, Object> cache, Object... injections){
|
private void injectDependencies(Constructor<?> constructor, Map<Class<?>, Object> cache, DependencyInjector injector){
|
||||||
Class<?>[] parameterTypes = constructor.getParameterTypes();
|
Parameter[] parameters = constructor.getParameters();
|
||||||
Object[] parameters = new Object[parameterTypes.length];
|
Object[] injections = new Object[parameters.length];
|
||||||
for(int i = 0; i < parameterTypes.length; i++){
|
for(int i = 0; i < parameters.length; i++){
|
||||||
Class<?> type = parameterTypes[i];
|
Parameter parameter = parameters[i];
|
||||||
|
Class<?> type = parameter.getType();
|
||||||
Object dependency = cache.get(type);
|
Object dependency = cache.get(type);
|
||||||
if(dependency != null){
|
if(dependency != null) injections[i] = dependency;
|
||||||
parameters[i] = dependency;
|
else if((injections[i] = injector.applyDependency(constructor, parameter, cache)) == null) throw new IllegalArgumentException("No dependency for type "+type);
|
||||||
}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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
Response response = (Response) constructor.newInstance(parameters);
|
Response response = (Response) constructor.newInstance(injections);
|
||||||
register(response);
|
register(response);
|
||||||
System.out.println("registerd "+response.getClass());
|
System.out.println("registerd "+response.getClass());
|
||||||
} catch (Exception e){
|
} catch (Exception e){
|
||||||
|
|
Loading…
Add table
Reference in a new issue