Skip to content
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

JavaDependencyInjection #1001

Open
wants to merge 45 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
0d67326
Component.java
VladSlob Sep 3, 2024
53cd600
Inject.java
VladSlob Sep 3, 2024
03a53f1
Injector.java
VladSlob Sep 3, 2024
e503d73
Main.java
VladSlob Sep 3, 2024
c789aaa
Injector.java
VladSlob Sep 3, 2024
5a09b0e
Injector.java
VladSlob Sep 3, 2024
3f94cf8
Injector.java
VladSlob Sep 3, 2024
2b1ec9c
Injector.java
VladSlob Sep 3, 2024
2e0e090
Injector.java
VladSlob Sep 3, 2024
45cd671
Injector.java
VladSlob Sep 3, 2024
b493b07
ProductServiceImpl.java
VladSlob Sep 3, 2024
856a733
ProductParserImpl.java
VladSlob Sep 3, 2024
d6dc2c8
FileReaderServiceImpl.java
VladSlob Sep 3, 2024
78ea73e
ProductService.java
VladSlob Sep 3, 2024
4c13282
ProductParser.java
VladSlob Sep 3, 2024
e8b95d3
FileReaderService.java
VladSlob Sep 3, 2024
7098a7c
ProductServiceImpl.java
VladSlob Sep 3, 2024
5e7ab09
ProductParserImpl.java
VladSlob Sep 3, 2024
e203ab6
FileReaderServiceImpl.java
VladSlob Sep 3, 2024
2b29161
ProductService.java
VladSlob Sep 3, 2024
3885bd4
ProductParser.java
VladSlob Sep 3, 2024
b2265bd
FileReaderService.java
VladSlob Sep 3, 2024
e51f181
ProductService.java
VladSlob Sep 3, 2024
228b388
ProductServiceImpl.java
VladSlob Sep 3, 2024
1c88d9a
ProductParserImpl.java
VladSlob Sep 3, 2024
7e19762
Product.java
VladSlob Sep 3, 2024
287c2a0
ProductService.java
VladSlob Sep 3, 2024
3b54686
ProductServiceImpl.java
VladSlob Sep 3, 2024
063f2d1
ProductParserImpl.java
VladSlob Sep 3, 2024
10418ed
FileReaderServiceImpl.java
VladSlob Sep 3, 2024
a7c7248
Product.java
VladSlob Sep 3, 2024
a48cf47
Component.java
VladSlob Sep 4, 2024
416e7ee
Injector.java
VladSlob Sep 4, 2024
95706d6
Injector.java
VladSlob Sep 4, 2024
99310cc
Main.java
VladSlob Sep 4, 2024
79a082c
Inject.java
VladSlob Sep 5, 2024
7890514
Product.java
VladSlob Sep 5, 2024
ee629d1
ProductParser.java
VladSlob Sep 5, 2024
8be9221
ProductService.java
VladSlob Sep 5, 2024
981fa13
FileReaderServiceImpl.java
VladSlob Sep 5, 2024
8b88d9e
ProductParserImpl.java
VladSlob Sep 5, 2024
c42aefb
ProductServiceImpl.java
VladSlob Sep 5, 2024
85fed85
Injector.java
VladSlob Sep 5, 2024
6946bad
Main.java
VladSlob Sep 5, 2024
f1f5813
Injector.java
VladSlob Sep 5, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions src/main/java/mate.academy/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,9 @@
import mate.academy.service.ProductService;

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(ProductService.class);
List<Product> products = productService.getAllFromFile("products.txt");
products.forEach(System.out::println);
}
Expand Down
5 changes: 4 additions & 1 deletion src/main/java/mate.academy/lib/Component.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package mate.academy.lib;

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

@Retention(RetentionPolicy.RUNTIME)
public @interface Component {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to the checklist, custom annotations should have a @Target annotation to specify where this annotation can be used. For example, if @Component is meant to be used on classes, you should add @Target(ElementType.TYPE).

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to the checklist, custom annotations should have a @target annotation to specify where this annotation can be used. For example, if @component is meant to be used on classes, you should add @target(ElementType.TYPE).

}
5 changes: 4 additions & 1 deletion src/main/java/mate.academy/lib/Inject.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package mate.academy.lib;

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

@Retention(RetentionPolicy.RUNTIME)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add target

public @interface Inject {
}
50 changes: 49 additions & 1 deletion src/main/java/mate.academy/lib/Injector.java
Original file line number Diff line number Diff line change
@@ -1,13 +1,61 @@
package mate.academy.lib;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

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;
if (!interfaceClazz.isInterface()) {
throw new RuntimeException("Only interfaces are supported");

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The exception message could be more informative. According to the checklist, when throwing an exception, it should contain an informative message. Consider including the type of the class that is not an interface.

}

Class<?> implClass = findImplementation(interfaceClazz);
if (implClass == null || !implClass.isAnnotationPresent(Component.class)) {
throw new RuntimeException("No implementation found for " + interfaceClazz.getName());

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The exception message should be more informative and include the reason why the implementation wasn't found. According to the checklist, the message should indicate the missing @Component annotation if that's the case.

}

return createInstance(implClass);
}

private Class<?> findImplementation(Class<?> interfaceClazz) {
// This method should return the implementation class for the given interface
// For simplicity, let's assume we have a hardcoded map of implementations
Map<Class<?>, Class<?>> implementations = Map.of(
ProductService.class, ProductServiceImpl.class,
ProductParser.class, ProductParserImpl.class,
FileReaderService.class, FileReaderServiceImpl.class

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The implementations map should be a class field instead of being created in the findImplementation method. This way, it's only initialized once and can be reused, which is more efficient.

);
return implementations.get(interfaceClazz);
}

private Object createInstance(Class<?> implClass) {
if (instances.containsKey(implClass)) {
return instances.get(implClass);
}

try {
Object instance = implClass.getDeclaredConstructor().newInstance();
instances.put(implClass, instance);

for (Field field : implClass.getDeclaredFields()) {
if (field.isAnnotationPresent(Inject.class)) {
field.setAccessible(true);
Object fieldInstance = getInstance(field.getType());
field.set(instance, fieldInstance);
}
}

return instance;
} catch (ReflectiveOperationException e) {
throw new RuntimeException("Failed to create instance of " + implClass.getName(), e);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of catching multiple exceptions separately, it's recommended to catch their common parent, ReflectiveOperationException, to simplify the code as per the checklist.

}
}
}
Loading