Skip to content

Commit

Permalink
improve code comments
Browse files Browse the repository at this point in the history
  • Loading branch information
tuhuynh27 committed Jun 29, 2024
1 parent fd1bd2a commit 0b8a4d3
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 31 deletions.
65 changes: 53 additions & 12 deletions src/main/java/dev/keva/ioc/KevaIoC.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import dev.keva.ioc.annotation.*;
import dev.keva.ioc.core.BeanContainer;
import dev.keva.ioc.core.CircularDetector;
import dev.keva.ioc.core.CircularDependencyDetector;
import dev.keva.ioc.core.ImplementationContainer;
import dev.keva.ioc.exception.IoCBeanNotFound;
import dev.keva.ioc.exception.IoCCircularDepException;
Expand All @@ -19,10 +19,48 @@
import java.net.URISyntaxException;
import java.util.*;

/**
* KevaIoC - A lightweight dependency injection and inversion of control container.
* The class provides mechanisms for scanning, registering, and resolving dependencies among components
* marked with specific annotations within a Java application. It supports component lifecycle management
* through dependency injection patterns such as constructor injection, setter injection, and field injection.
*
* Key Features:
* - Component scanning based on package names and annotations.
* - Registration of components, either predefined or discovered via component scanning.
* - Resolution of components ensuring dependencies are satisfied and handling lifecycle appropriately.
* - Detection and handling of circular dependencies among components.
* - Exception handling to manage errors related to bean instantiation, circular dependencies, and missing beans.
*
* Usage:
* - To use this container, the user must call the static method `initBeans` with the main class and any predefined beans.
* - Beans can be fetched using the `getBean` method by providing the class type.
*
* Method Execution Flow:
* 1. `initBeans`: Initializes the IoC container with an optional list of predefined beans. This method handles all
* initial setup including scanning components, registering beans, and handling any exceptions that occur during initialization.
* 2. `initWrapper`: Called by `initBeans`, this method performs the detailed initialization sequence including:
* a. Registering predefined beans if provided.
* b. Component scanning using annotations to discover and register additional beans.
* 3. `init`: Helper method called by `initWrapper` to perform scanning within a specific package, it handles:
* a. Registering the container itself as a bean.
* b. Scanning for implementations, configurations, and components within the package.
* 4. `scanImplementations`, `scanConfigurationClass`, `scanComponentClasses`: These methods are used to find and register beans based on different criteria like annotated classes or methods within classes.
* 5. `newInstanceWrapper`: Handles instantiation of a class, managing circular dependencies and injecting necessary dependencies.
* 6. `_getBean`: Overloaded methods that resolve and return beans by type, handling instantiation if not already present in the container.
* 7. `fieldInject`, `setterInject`: Methods for performing dependency injection into annotated fields and setter methods respectively.
*
* Exceptions:
* - The class handles various exceptions that may arise during the operation of the IoC container such as `IoCException`,
* `IoCBeanNotFound`, and `IoCCircularDepException`. These are typically re-thrown as `IoCException` with appropriate error messages.
*
* This class is part of the `dev.keva.ioc` package and depends on various other classes within the same package and third-party
* libraries such as `org.reflections.Reflections` for component scanning based on annotations.
*/
public class KevaIoC {
private final BeanContainer beanContainer = new BeanContainer();
private final ImplementationContainer implementationContainer = new ImplementationContainer();
private final CircularDetector circularDetector = new CircularDetector();
private final CircularDependencyDetector circularDependencyDetector = new CircularDependencyDetector();

private KevaIoC() {
}
Expand Down Expand Up @@ -121,7 +159,6 @@ private void scanConfigurationClass(List<Class<?>> classes) throws IoCCircularDe
Class<?> configurationClass = configurationClassesQ.removeFirst();
try {
Object instance = configurationClass.getConstructor().newInstance();
circularDetector.detect(configurationClass);
scanConfigurationBeans(configurationClass, instance);
} catch (IoCBeanNotFound e) {
configurationClassesQ.addLast(configurationClass);
Expand Down Expand Up @@ -160,17 +197,21 @@ private void scanConfigurationBeans(Class<?> clazz, Object classInstance) throws

private Object newInstanceWrapper(Class<?> clazz) throws InvocationTargetException,
IllegalAccessException, InstantiationException, NoSuchMethodException, IoCBeanNotFound, IoCCircularDepException {
if (beanContainer.containsBean(clazz)) {
return beanContainer.getBean(clazz);
}
circularDependencyDetector.startInstantiation(clazz);

circularDetector.detect(clazz);
try {
if (beanContainer.containsBean(clazz)) {
return beanContainer.getBean(clazz);
}

Object instance = newInstance(clazz);
beanContainer.putBean(clazz, instance);
fieldInject(clazz, instance);
setterInject(clazz, instance);
return instance;
Object instance = newInstance(clazz);
beanContainer.putBean(clazz, instance);
fieldInject(clazz, instance);
setterInject(clazz, instance);
return instance;
} finally {
circularDependencyDetector.finishInstantiation(clazz);
}
}

private Object newInstance(Class<?> clazz) throws IllegalAccessException,
Expand Down
20 changes: 20 additions & 0 deletions src/main/java/dev/keva/ioc/core/CircularDependencyDetector.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package dev.keva.ioc.core;

import dev.keva.ioc.exception.IoCCircularDepException;

import java.util.*;

public class CircularDependencyDetector {
private final Set<Class<?>> instantiationInProgress = new HashSet<>();

public void startInstantiation(Class<?> clazz) throws IoCCircularDepException {
if (instantiationInProgress.contains(clazz)) {
throw new IoCCircularDepException("Circular dependency detected while instantiating " + clazz.getName());
}
instantiationInProgress.add(clazz);
}

public void finishInstantiation(Class<?> clazz) {
instantiationInProgress.remove(clazz);
}
}
19 changes: 0 additions & 19 deletions src/main/java/dev/keva/ioc/core/CircularDetector.java

This file was deleted.

0 comments on commit 0b8a4d3

Please sign in to comment.