Skip to content

Commit

Permalink
implemented an injector using annotations.
Browse files Browse the repository at this point in the history
  • Loading branch information
ArtemReizer committed Aug 8, 2023
1 parent 7c2827f commit 1bbe1c1
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 4 deletions.
4 changes: 3 additions & 1 deletion src/main/java/mate.academy/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@
import mate.academy.lib.Injector;
import mate.academy.model.Product;
import mate.academy.service.ProductService;
import mate.academy.service.impl.ProductServiceImpl;

public class Main {

public static void main(String[] args) {
// Please test your Injector here. Feel free to push this class as a part of your solution
Injector injector = Injector.getInjector();
ProductService productService = null;
ProductService productService = (ProductService) injector
.getInstance(ProductServiceImpl.class);
List<Product> products = productService.getAllFromFile("products.txt");
products.forEach(System.out::println);
}
Expand Down
8 changes: 7 additions & 1 deletion src/main/java/mate.academy/lib/Component.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
package mate.academy.lib;

public @interface Component {
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Component {
}
8 changes: 7 additions & 1 deletion src/main/java/mate.academy/lib/Inject.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
package mate.academy.lib;

public @interface Inject {
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Inject {
}
69 changes: 68 additions & 1 deletion src/main/java/mate.academy/lib/Injector.java
Original file line number Diff line number Diff line change
@@ -1,13 +1,80 @@
package mate.academy.lib;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
import mate.academy.service.FileReaderService;
import mate.academy.service.ProductParser;
import mate.academy.service.ProductService;
import mate.academy.service.impl.FileReaderServiceImpl;
import mate.academy.service.impl.ProductParserImpl;
import mate.academy.service.impl.ProductServiceImpl;

public class Injector {
private static final Injector injector = new Injector();
private final Map<Class<?>, Object> instances = new HashMap<>();

public static Injector getInjector() {
return injector;
}

public Object getInstance(Class<?> interfaceClazz) {
return null;
Class<?> clazz = findImplementation(interfaceClazz);
isClassValid(clazz);
Object clazzImplementationInstance = null;
Field[] declaredFields = interfaceClazz.getDeclaredFields();
for (Field field : declaredFields) {
if (field.isAnnotationPresent(Inject.class)) {
Object fieldInstance = getInstance(field.getType());
clazzImplementationInstance = createNewInstance(clazz);
try {
field.setAccessible(true);
field.set(clazzImplementationInstance, fieldInstance);
} catch (IllegalAccessException e) {
throw new RuntimeException("Can't initialize field value. Class: "
+ clazz.getName() + ". Field: " + field.getName());
}
}
}
if (clazzImplementationInstance == null) {
clazzImplementationInstance = createNewInstance(clazz);
}
return clazzImplementationInstance;
}

private void isClassValid(Class<?> clazz) {
if (!clazz.isAnnotationPresent(Component.class)) {
throw new RuntimeException("Class: " + clazz.getName()
+ " isn't valid, because isn't declared as @Component");
}
}

private Object createNewInstance(Class<?> clazz) {
if (instances.containsKey(clazz)) {
return instances.get(clazz);
}
try {
Constructor<?> constructor = clazz.getConstructor();
Object instance = constructor.newInstance();
instances.put(clazz, instance);
return instance;
} catch (NoSuchMethodException | InvocationTargetException
| InstantiationException | IllegalAccessException e) {
throw new RuntimeException("Can't create new instance of " + clazz.getName());
}

}

private Class<?> findImplementation(Class<?> interfaceClazz) {
Map<Class<?>, Class<?>> interfaceImplementation = new HashMap<>();
interfaceImplementation.put(ProductService.class, ProductServiceImpl.class);
interfaceImplementation.put(ProductParser.class, ProductParserImpl.class);
interfaceImplementation.put(FileReaderService.class, FileReaderServiceImpl.class);
if (interfaceClazz.isInterface()) {
return interfaceImplementation.get(interfaceClazz);
}
return interfaceClazz;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
import java.io.IOException;
import java.nio.file.Files;
import java.util.List;
import mate.academy.lib.Component;
import mate.academy.service.FileReaderService;

@Component
public class FileReaderServiceImpl implements FileReaderService {
@Override
public List<String> readFile(String fileName) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package mate.academy.service.impl;

import java.math.BigDecimal;
import mate.academy.lib.Component;
import mate.academy.model.Product;
import mate.academy.service.ProductParser;

@Component
public class ProductParserImpl implements ProductParser {
public static final int ID_POSITION = 0;
public static final int NAME_POSITION = 1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,18 @@

import java.util.List;
import java.util.stream.Collectors;
import mate.academy.lib.Component;
import mate.academy.lib.Inject;
import mate.academy.model.Product;
import mate.academy.service.FileReaderService;
import mate.academy.service.ProductParser;
import mate.academy.service.ProductService;

@Component
public class ProductServiceImpl implements ProductService {
@Inject
private ProductParser productParser;
@Inject
private FileReaderService fileReaderService;

@Override
Expand Down

0 comments on commit 1bbe1c1

Please sign in to comment.