-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Jv dependency injection #1262
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Jv dependency injection #1262
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,12 @@ | ||
| package mate.academy.lib; | ||
|
|
||
| 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.TYPE) | ||
| public @interface Component { | ||
|
|
||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,12 @@ | ||
| package mate.academy.lib; | ||
|
|
||
| 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 { | ||
|
|
||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,13 +1,74 @@ | ||
| package mate.academy.lib; | ||
|
|
||
| import java.lang.reflect.Constructor; | ||
| import java.lang.reflect.Field; | ||
| 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 Map<Class<?>, Object> instances = new HashMap<>(); | ||
| private final Map<Class<?>, Class<?>> interfaceImplementations = Map.of( | ||
| FileReaderService.class, FileReaderServiceImpl.class, | ||
| ProductParser.class, ProductParserImpl.class, | ||
| ProductService.class, ProductServiceImpl.class | ||
| ); | ||
|
|
||
| public static Injector getInjector() { | ||
|
|
||
| return injector; | ||
| } | ||
|
|
||
| public Object getInstance(Class<?> interfaceClazz) { | ||
| return null; | ||
| Class<?> clazz = findImplementation(interfaceClazz); | ||
|
|
||
| if (!clazz.isAnnotationPresent(Component.class)) { | ||
| throw new RuntimeException("Can't create class!"); | ||
| } | ||
| Object clazzImplementationInstance = createNewInstance(clazz); | ||
| Field[] declaredFields = clazz.getDeclaredFields(); | ||
| for (Field fields : declaredFields) { | ||
| if (fields.isAnnotationPresent(Inject.class)) { | ||
| Object fieldsInstance = getInstance(fields.getType()); | ||
|
|
||
| try { | ||
| fields.setAccessible(true); | ||
| fields.set(clazzImplementationInstance, fieldsInstance); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. CHECKLIST ITEM #8 VIOLATION: Replace |
||
| } catch (IllegalAccessException e) { | ||
| throw new RuntimeException("Can't initialize field value." | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This violates checklist item #7: The caught exception is not chained to the RuntimeException. Use the constructor's second parameter: |
||
| + "Class: " + clazz.getName() + ". Field: " | ||
|
Comment on lines
+42
to
+45
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. CHECKLIST ITEM #7 VIOLATION: The exception is not chained to the RuntimeException. Use |
||
| + fields.getName()); | ||
| } | ||
| } | ||
| } | ||
| return clazzImplementationInstance; | ||
| } | ||
|
|
||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Checklist item #4 violated: There's no check for |
||
| 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 (ReflectiveOperationException e) { | ||
| throw new RuntimeException("Can't create a new instance of " + clazz.getName(), e); | ||
| } | ||
| } | ||
|
|
||
| private Class<?> findImplementation(Class<?> interfaceClazz) { | ||
| if (interfaceClazz.isInterface()) { | ||
| return interfaceImplementations.get(interfaceClazz); | ||
| } | ||
| return interfaceClazz; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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 | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Checklist item #6 violation: interfaceImplementations should be initialized using Map.of() as a class field, not populated with put() inside findImplementation(). Change line 20 to: Map<Class, Class> interfaceImplementations = Map.of(FileReaderService.class, FileReaderServiceImpl.class, ProductParser.class, ProductParserImpl.class, ProductService.class, ProductServiceImpl.class); |
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
@Componentcheck happens AFTERcreateNewInstance()is called at line 26. This violates checklist item #4 - the check must happen BEFORE instantiation. Move this validation tocreateNewInstance()or before calling it.