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 all 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
9 changes: 2 additions & 7 deletions src/main/java/mate.academy/Main.java
Original file line number Diff line number Diff line change
@@ -1,17 +1,12 @@
package mate.academy;

import java.util.List;
import mate.academy.lib.Injector;
import mate.academy.model.Product;
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;
List<Product> products = productService.getAllFromFile("products.txt");
products.forEach(System.out::println);
ProductService productService = injector.getInstance(ProductService.class);
productService.getAllFromFile("products.txt").forEach(System.out::println);
}
}
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;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
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).

}
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)

Choose a reason for hiding this comment

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

add target

@Target(ElementType.FIELD)
public @interface Inject {
}
48 changes: 46 additions & 2 deletions src/main/java/mate.academy/lib/Injector.java
Original file line number Diff line number Diff line change
@@ -1,13 +1,57 @@
package mate.academy.lib;

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 Map<Class<?>, Class<?>> interfaceToImplementation = new HashMap<>();
private static final Map<Class<?>, Object> instances = new HashMap<>();
private static final Injector injector = new Injector();

static {
interfaceToImplementation.put(ProductService.class, ProductServiceImpl.class);
interfaceToImplementation.put(ProductParser.class, ProductParserImpl.class);
interfaceToImplementation.put(FileReaderService.class, FileReaderServiceImpl.class);
}

private Injector() {
}

public static Injector getInjector() {
return injector;
}

public Object getInstance(Class<?> interfaceClazz) {
return null;
public <T> T getInstance(Class<T> interfaceClazz) {
Class<?> implClass = interfaceToImplementation.get(interfaceClazz);

Choose a reason for hiding this comment

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

This is not full implementation os Injector

The convention is to use Component on the classes that are used for instance creation (usually these are interface implementations) and Inject to mark fields that need to be initialized. If the Component annotation is missing above the class, we shouldn't be able to create an instance of this class in Injector, and we should throw an exception

Don't forget about annotations checks in your Injector class.
Let's check instances map before new instance creation.

if (implClass == null) {
throw new RuntimeException("No implementation found for " + interfaceClazz.getName());
}
if (!implClass.isAnnotationPresent(Component.class)) {
throw new RuntimeException("Implementation " + implClass.getName()
+ " is not annotated with @Component");
}
if (instances.containsKey(implClass)) {
return (T) instances.get(implClass);
}
try {
T instance = (T) implClass.getDeclaredConstructor().newInstance();
for (Field field : implClass.getDeclaredFields()) {
if (field.isAnnotationPresent(Inject.class)) {
field.setAccessible(true);
field.set(instance, getInstance(field.getType()));
}
}
instances.put(implClass, instance);
return instance;
} catch (Exception e) {
throw new RuntimeException("Can't create instance of " + implClass.getName(), e);
}
}
}
39 changes: 5 additions & 34 deletions src/main/java/mate.academy/model/Product.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,9 @@
import java.math.BigDecimal;

public class Product {

Choose a reason for hiding this comment

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

revert changes

private Long id;
private String name;
private String category;
private String description;
private BigDecimal price;

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}
private String description;

public String getName() {
return name;
Expand All @@ -25,12 +15,12 @@ public void setName(String name) {
this.name = name;
}

public String getCategory() {
return category;
public BigDecimal getPrice() {
return price;
}

public void setCategory(String category) {
this.category = category;
public void setPrice(BigDecimal price) {
this.price = price;
}

public String getDescription() {
Expand All @@ -40,23 +30,4 @@ public String getDescription() {
public void setDescription(String description) {
this.description = description;
}

public BigDecimal getPrice() {
return price;
}

public void setPrice(BigDecimal price) {
this.price = price;
}

@Override
public String toString() {
return "Product{"
+ "id=" + id
+ ", name='" + name + '\''
+ ", category='" + category + '\''
+ ", description='" + description + '\''
+ ", price=" + price
+ '}';
}
}
7 changes: 3 additions & 4 deletions src/main/java/mate.academy/service/ProductParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@

public interface ProductParser {
/**
* Parse the productInfo and return created {@link Product} object.
* The `productInfo` could be received from any source.
* For example from file with all products stored in the shop.
* @param productInfo - the information about a product
* Parses a product from a string.
*
* @param productInfo the string containing product information
* @return newly create {@link Product} object based on the `productInfo` input.
*/
Product parse(String productInfo);
Expand Down
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
14 changes: 6 additions & 8 deletions src/main/java/mate.academy/service/impl/ProductParserImpl.java
Original file line number Diff line number Diff line change
@@ -1,25 +1,23 @@
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;
public static final int CATEGORY_POSITION = 2;
public static final int DESCRIPTION_POSITION = 3;
public static final int PRICE_POSITION = 4;
private static final int NAME_POSITION = 0;
private static final int PRICE_POSITION = 1;
private static final int DESCRIPTION_POSITION = 2;

@Override
public Product parse(String productInfo) {
String[] data = productInfo.split(",");
Product product = new Product();
product.setId(Long.valueOf(data[ID_POSITION]));
product.setName(data[NAME_POSITION]);
product.setCategory(data[CATEGORY_POSITION]);
product.setDescription(data[DESCRIPTION_POSITION]);
product.setPrice(new BigDecimal(data[PRICE_POSITION]));
product.setDescription(data[DESCRIPTION_POSITION]);
return product;
}
}
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
Loading