-
Notifications
You must be signed in to change notification settings - Fork 998
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
base: main
Are you sure you want to change the base?
JavaDependencyInjection #1001
Changes from all commits
0d67326
53cd600
03a53f1
e503d73
c789aaa
5a09b0e
3f94cf8
2b1ec9c
2e0e090
45cd671
b493b07
856a733
d6dc2c8
78ea73e
4c13282
e8b95d3
7098a7c
5e7ab09
e203ab6
2b29161
3885bd4
b2265bd
e51f181
228b388
1c88d9a
7e19762
287c2a0
3b54686
063f2d1
10418ed
a7c7248
a48cf47
416e7ee
95706d6
99310cc
79a082c
7890514
ee629d1
8be9221
981fa13
8b88d9e
c42aefb
85fed85
6946bad
f1f5813
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,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); | ||
} | ||
} |
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 { | ||
} |
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) | ||
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. add target |
||
@Target(ElementType.FIELD) | ||
public @interface Inject { | ||
} |
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); | ||
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 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. |
||
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); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,19 +3,9 @@ | |
import java.math.BigDecimal; | ||
|
||
public class Product { | ||
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. 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; | ||
|
@@ -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() { | ||
|
@@ -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 | ||
+ '}'; | ||
} | ||
} |
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; | ||
} | ||
} |
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.
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)
.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.
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).