Skip to content

Commit

Permalink
study: DIContainer 리펙토링
Browse files Browse the repository at this point in the history
  • Loading branch information
echo724 committed Sep 28, 2023
1 parent a423a95 commit 68233c4
Showing 1 changed file with 59 additions and 38 deletions.
97 changes: 59 additions & 38 deletions study/src/test/java/di/stage4/annotations/DIContainer.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,56 +24,77 @@ public DIContainer(final Set<Class<?>> classes) {

private Set<Object> instantiateBeans(final Set<Class<?>> classes) {
final Map<Class<?>, Object> classObjectMap = new HashMap<>();
final List<Class<?>> sortedClasses = classes.stream()
final List<Class<?>> sortedClasses = sortClassByLessDependnecies(classes);
for (final Class<?> sortedClass : sortedClasses) {
if (sortedClass.getConstructors().length != 0) {
injectConstructorDependency(sortedClass, classObjectMap);
}
injectFieldDependency(sortedClass, classObjectMap);
}
return new HashSet<>(classObjectMap.values());
}

private List<Class<?>> sortClassByLessDependnecies(final Set<Class<?>> classes) {
return classes.stream()
.sorted(Comparator
.comparing(a -> ((Class<?>) a).getDeclaredFields().length)
.reversed()
)
.collect(Collectors.toList());
System.out.println("sortedClasses = " + sortedClasses);
for (final Class<?> sortedClass : sortedClasses) {
if (sortedClass.getConstructors().length != 0) {
final Constructor<?> defaultConstructor = sortedClass.getConstructors()[0];
if (defaultConstructor.getParameterCount() != 0) {
final Class<?>[] parameterTypes = defaultConstructor.getParameterTypes();
final Object[] parameters = new Object[parameterTypes.length];
for (int i = 0; i < parameterTypes.length; i++) {
parameters[i] = classObjectMap.get(parameterTypes[i]);
}
try {
putInterfaceOrClass(sortedClass, classObjectMap, defaultConstructor, parameters);
} catch (Exception e) {
throw new RuntimeException(e);
}
} else {
final Constructor<?> constructor = sortedClass.getConstructors()[0];
}

private void injectFieldDependency(final Class<?> sortedClass, final Map<Class<?>, Object> classObjectMap) {
Arrays.stream(sortedClass.getDeclaredFields())
.filter(field -> field.isAnnotationPresent(Inject.class))
.forEach(field -> {
try {
putInterfaceOrClass(sortedClass, classObjectMap, constructor);
field.setAccessible(true);
final Object instance = classObjectMap.getOrDefault(sortedClass, instantiatePrivateConstructor(sortedClass));
field.set(instance, classObjectMap.get(field.getType()));
classObjectMap.put(sortedClass, instance);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
} else if (sortedClass.getDeclaredFields().length != 0) {
Arrays.stream(sortedClass.getDeclaredFields())
.filter(field -> field.isAnnotationPresent(Inject.class))
.forEach(field -> {
try {
field.setAccessible(true);
final Constructor<?> declaredConstructor = sortedClass.getDeclaredConstructors()[0];
declaredConstructor.setAccessible(true);
final Object instance = declaredConstructor.newInstance();
field.set(instance, classObjectMap.get(field.getType()));
classObjectMap.put(sortedClass, instance);
} catch (Exception e) {
throw new RuntimeException(e);
}
});
}
});
}

private Object instantiatePrivateConstructor(final Class<?> sortedClass) throws InstantiationException, IllegalAccessException, InvocationTargetException {
final Constructor<?> declaredConstructor = sortedClass.getDeclaredConstructors()[0];
declaredConstructor.setAccessible(true);
return declaredConstructor.newInstance();
}

private void injectConstructorDependency(final Class<?> sortedClass, final Map<Class<?>, Object> classObjectMap) {
final Constructor<?> defaultConstructor = sortedClass.getConstructors()[0];
if (defaultConstructor.getParameterCount() != 0) {
instantiateBeanWithParameters(sortedClass, classObjectMap, defaultConstructor);
} else {
instantiateBean(sortedClass, classObjectMap, defaultConstructor);
}
}

private void instantiateBean(final Class<?> sortedClass, final Map<Class<?>, Object> classObjectMap, final Constructor<?> defaultConstructor) {
try {
putInterfaceOrClass(sortedClass, classObjectMap, defaultConstructor);
} catch (Exception e) {
throw new RuntimeException(e);
}
}

private void instantiateBeanWithParameters(final Class<?> sortedClass, final Map<Class<?>, Object> classObjectMap, final Constructor<?> defaultConstructor) {
final Class<?>[] parameterTypes = defaultConstructor.getParameterTypes();
final Object[] parameters = new Object[parameterTypes.length];
for (int i = 0; i < parameterTypes.length; i++) {
parameters[i] = classObjectMap.get(parameterTypes[i]);
}
try {
putInterfaceOrClass(sortedClass, classObjectMap, defaultConstructor, parameters);
} catch (Exception e) {
throw new RuntimeException(e);
}
return new HashSet<>(classObjectMap.values());
}

private static void putInterfaceOrClass(final Class<?> sortedClass, final Map<Class<?>, Object> classObjectMap, final Constructor<?> constructor, final Object... parameters) throws InstantiationException, IllegalAccessException, InvocationTargetException {
private void putInterfaceOrClass(final Class<?> sortedClass, final Map<Class<?>, Object> classObjectMap, final Constructor<?> constructor, final Object... parameters) throws InstantiationException, IllegalAccessException, InvocationTargetException {
final Class<?>[] interfaces = sortedClass.getInterfaces();
for (final Class<?> anInterface : interfaces) {
classObjectMap.put(anInterface, constructor.newInstance(parameters));
Expand Down

0 comments on commit 68233c4

Please sign in to comment.