Each folder has its own README!
This is a 4 part piece in which I go through:
- Java Persistence API (JPA)
- Content and Dependency Injection (CDI)
- Rest Services in Java EE
- Combining Rest services, CDI and JPA
- What is Dependency Inversion?
- What is Dependency Injection?
- How to switch which out which class gets injected
In this example each class creates an instance of the next class in which it calls methods inside it.
In this example, by using an interface in which Friend and Enemy both inherit from, it slightly easier to switch out friend and enemy
If class A calls class B, A is the "dependant" and B is the "dependency". A relies on B.
Dependencies aren't great because it means that the method can't be as reused (Think open closed principle).
In ths example, World can be reused with any class that implements Relation.
This is why it is so useful to code to an interface - it allows for many different implemenetations. It also means that your code is extensible without modification.
This now means that instead of class A depending on class B, class A depends on a Relation abstraction, which can be interchanged easily with a different concretion. So whether B gets called or not depends on class A, B is now dependant on A => dependency inversion.
To switch out the implementation is probably going to need a lot of changing to source code. With dependency injection, we simplify it.
By having a 'Container' that manages beans (classes), the container will decide which bean to inject for the interface!
We can make a bunch of implementations, however if we have more than one, it will get confused - because it won't know which one to inject. So we can tag the Enemy with the @Alternative annotation. In the beans.xml we can say that we want to use the following alternative instead of the normal implementation.
Try changing the configuration in the beans.xml and see how the result coming back changes.
Finally we might want to say - inject the friendly types - if there is more than one implementation which is friendly, we can keep applying tags until it is specifying a single class. These tags are then very easy to change out.
It will do its best to match the tags of the implementation with what we want to inject in.
If no tag is given ie:
@Inject
Interface interface
It will actually tag it with the @Default annotation so it will look something similar to this instead:
@Inject
@Default
Interface interface;
The default tag gets applied (even if we don't explicit write it in)