A simple Dependency Injection (DI) framework can be built using Java Reflection by scanning classes for custom annotations, creating dependency objects dynamically, and injecting them into target classes at runtime. This approach separates object creation from object usage, resulting in loosely coupled and more maintainable code.
Key Points: • Reflection can inspect classes, fields, constructors, and annotations during runtime to identify dependencies. • Custom annotations such as @Inject can mark fields that require automatic dependency injection. • Dependency Injection improves modularity, testability, and maintainability by removing direct object creation from business classes.
Example: Suppose a UserService depends on a UserRepository. Instead of creating the repository using new UserRepository(), a DI framework detects the @Inject annotation and automatically creates and injects the required dependency at runtime.
Code Example:
import java.lang.annotation.*;
import java.lang.reflect.Field;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@interface Inject {
}
class UserRepository {
public void save() {
System.out.println("User Saved");
}
}
class UserService {
@Inject
private UserRepository repository;
public void execute() {
repository.save();
}
}
class SimpleDIContainer {
public static <T> T create(Class<T> clazz)
throws Exception {
T instance =
clazz.getDeclaredConstructor()
.newInstance();
for (Field field : clazz.getDeclaredFields()) {if (field.isAnnotationPresent(
Inject.class)) {
Object dependency =
field.getType().getDeclaredConstructor()
.newInstance();
field.setAccessible(true);
field.set(instance, dependency);
}
}
return instance;
}
}
public class Main {
public static void main(String[] args)
throws Exception {
UserService service =
SimpleDIContainer.create(
UserService.class);
service.execute();
}
}Interview Tip: A concise interview answer is: I would use Reflection to scan classes for custom annotations such as @Inject, dynamically create dependency instances, and inject them into target objects at runtime. This is the core concept behind Dependency Injection frameworks like Spring, which use reflection extensively to manage object creation and wiring.