|
2 | 2 |
|
3 | 3 | import dev.keva.ioc.annotation.*;
|
4 | 4 | import dev.keva.ioc.core.BeanContainer;
|
5 |
| -import dev.keva.ioc.core.CircularDetector; |
| 5 | +import dev.keva.ioc.core.CircularDependencyDetector; |
6 | 6 | import dev.keva.ioc.core.ImplementationContainer;
|
7 | 7 | import dev.keva.ioc.exception.IoCBeanNotFound;
|
8 | 8 | import dev.keva.ioc.exception.IoCCircularDepException;
|
|
19 | 19 | import java.net.URISyntaxException;
|
20 | 20 | import java.util.*;
|
21 | 21 |
|
| 22 | +/** |
| 23 | + * KevaIoC - A lightweight dependency injection and inversion of control container. |
| 24 | + * The class provides mechanisms for scanning, registering, and resolving dependencies among components |
| 25 | + * marked with specific annotations within a Java application. It supports component lifecycle management |
| 26 | + * through dependency injection patterns such as constructor injection, setter injection, and field injection. |
| 27 | + * |
| 28 | + * Key Features: |
| 29 | + * - Component scanning based on package names and annotations. |
| 30 | + * - Registration of components, either predefined or discovered via component scanning. |
| 31 | + * - Resolution of components ensuring dependencies are satisfied and handling lifecycle appropriately. |
| 32 | + * - Detection and handling of circular dependencies among components. |
| 33 | + * - Exception handling to manage errors related to bean instantiation, circular dependencies, and missing beans. |
| 34 | + * |
| 35 | + * Usage: |
| 36 | + * - To use this container, the user must call the static method `initBeans` with the main class and any predefined beans. |
| 37 | + * - Beans can be fetched using the `getBean` method by providing the class type. |
| 38 | + * |
| 39 | + * Method Execution Flow: |
| 40 | + * 1. `initBeans`: Initializes the IoC container with an optional list of predefined beans. This method handles all |
| 41 | + * initial setup including scanning components, registering beans, and handling any exceptions that occur during initialization. |
| 42 | + * 2. `initWrapper`: Called by `initBeans`, this method performs the detailed initialization sequence including: |
| 43 | + * a. Registering predefined beans if provided. |
| 44 | + * b. Component scanning using annotations to discover and register additional beans. |
| 45 | + * 3. `init`: Helper method called by `initWrapper` to perform scanning within a specific package, it handles: |
| 46 | + * a. Registering the container itself as a bean. |
| 47 | + * b. Scanning for implementations, configurations, and components within the package. |
| 48 | + * 4. `scanImplementations`, `scanConfigurationClass`, `scanComponentClasses`: These methods are used to find and register beans based on different criteria like annotated classes or methods within classes. |
| 49 | + * 5. `newInstanceWrapper`: Handles instantiation of a class, managing circular dependencies and injecting necessary dependencies. |
| 50 | + * 6. `_getBean`: Overloaded methods that resolve and return beans by type, handling instantiation if not already present in the container. |
| 51 | + * 7. `fieldInject`, `setterInject`: Methods for performing dependency injection into annotated fields and setter methods respectively. |
| 52 | + * |
| 53 | + * Exceptions: |
| 54 | + * - The class handles various exceptions that may arise during the operation of the IoC container such as `IoCException`, |
| 55 | + * `IoCBeanNotFound`, and `IoCCircularDepException`. These are typically re-thrown as `IoCException` with appropriate error messages. |
| 56 | + * |
| 57 | + * This class is part of the `dev.keva.ioc` package and depends on various other classes within the same package and third-party |
| 58 | + * libraries such as `org.reflections.Reflections` for component scanning based on annotations. |
| 59 | + */ |
22 | 60 | public class KevaIoC {
|
23 | 61 | private final BeanContainer beanContainer = new BeanContainer();
|
24 | 62 | private final ImplementationContainer implementationContainer = new ImplementationContainer();
|
25 |
| - private final CircularDetector circularDetector = new CircularDetector(); |
| 63 | + private final CircularDependencyDetector circularDependencyDetector = new CircularDependencyDetector(); |
26 | 64 |
|
27 | 65 | private KevaIoC() {
|
28 | 66 | }
|
@@ -121,7 +159,6 @@ private void scanConfigurationClass(List<Class<?>> classes) throws IoCCircularDe
|
121 | 159 | Class<?> configurationClass = configurationClassesQ.removeFirst();
|
122 | 160 | try {
|
123 | 161 | Object instance = configurationClass.getConstructor().newInstance();
|
124 |
| - circularDetector.detect(configurationClass); |
125 | 162 | scanConfigurationBeans(configurationClass, instance);
|
126 | 163 | } catch (IoCBeanNotFound e) {
|
127 | 164 | configurationClassesQ.addLast(configurationClass);
|
@@ -160,17 +197,21 @@ private void scanConfigurationBeans(Class<?> clazz, Object classInstance) throws
|
160 | 197 |
|
161 | 198 | private Object newInstanceWrapper(Class<?> clazz) throws InvocationTargetException,
|
162 | 199 | IllegalAccessException, InstantiationException, NoSuchMethodException, IoCBeanNotFound, IoCCircularDepException {
|
163 |
| - if (beanContainer.containsBean(clazz)) { |
164 |
| - return beanContainer.getBean(clazz); |
165 |
| - } |
| 200 | + circularDependencyDetector.startInstantiation(clazz); |
166 | 201 |
|
167 |
| - circularDetector.detect(clazz); |
| 202 | + try { |
| 203 | + if (beanContainer.containsBean(clazz)) { |
| 204 | + return beanContainer.getBean(clazz); |
| 205 | + } |
168 | 206 |
|
169 |
| - Object instance = newInstance(clazz); |
170 |
| - beanContainer.putBean(clazz, instance); |
171 |
| - fieldInject(clazz, instance); |
172 |
| - setterInject(clazz, instance); |
173 |
| - return instance; |
| 207 | + Object instance = newInstance(clazz); |
| 208 | + beanContainer.putBean(clazz, instance); |
| 209 | + fieldInject(clazz, instance); |
| 210 | + setterInject(clazz, instance); |
| 211 | + return instance; |
| 212 | + } finally { |
| 213 | + circularDependencyDetector.finishInstantiation(clazz); |
| 214 | + } |
174 | 215 | }
|
175 | 216 |
|
176 | 217 | private Object newInstance(Class<?> clazz) throws IllegalAccessException,
|
|
0 commit comments