Dependency injection (DI) είναι μια διαδικασία, στην οποία τα αντικείμενα ορίζουν τις εξαρτήσεις τους (τα άλλα αντικείμενα με τα οποία δουλεύουν), μόνο μέσω παραμέτρων κατασκευαστή, παραμέτρων σε μια μέθοδο- εργοστάσιου ή μέσω properties, τα οποία ορίζονται στο στιγμιότυπο αντικειμένου, αφού αυτό κατασκευαστεί ή επιστραφεί από μέθοδο-εργοστάσιο. Το container ύστερα κάνει inject τις εξαρτήσεις, όταν δημιουργεί το bean. Η διαδικασία είναι ουσιαστικά η αντίστροφη, από το να ελέγχει το αντικείμενο-bean την αρχικοποίηση ή την τοποθεσία των εξαρτήσεων του , χρησιμοποιώντας απευθείας κατασκευή των κλάσεων.
Ο κώδικας είναι πιο "καθαρός" εφαρμόζοντας DI και πετυχαίνουμε χαμηλή σύζευξη, όταν στα αντικείμενα παρέχονται οι εξαρτήσεις τους. Τα αντικείμενα δεν ψάχνουν τις εξαρτήσεις τους και δεν γνωρίζουν την τοποθεσία ή την κλάση των εξαρτήσεων. Έτσι, είναι πιο εύκολο να πραγματοποιηθούν test στις κλάσεις, ειδικά όταν οι εξαρτήσεις είναι διεπαφές ή αφηρημένες κλάσεις, οι οποίες επιτρέπουν, να χρησιμοποιηθούν mock implementations στα unit tests.
Υπάρχουν δύο είδη dependency injection : Constructor-based dependency injection και Setter-based dependency injection.
public class SimpleMovieLister {
// Η κλάση SimpleMovieLister εξαρτάται από τη MovieFinder
private MovieFinder movieFinder;
public SimpleMovieLister() {
this.movieFinder = new MovieFinder();
}
}
Η κλάση SimpleMovieLister χρησιμοποιεί ένα στιγμιότυπο της κλάσης MovieFinder και παρέχει η ίδια ένα στιγμιότυπο στο κώδικα, χρησιμοποιώντας το keyword new και τον κατασκευαστή MovieFinder().
Το Constructor-based DI πραγματοποιείται από το Container, καλώντας έναν κατασκευαστή με έναν αριθμό παραμέτρων, όπου το καθένα αναπαριστά μια εξάρτηση.
public class SimpleMovieLister {
// Η κλάση SimpleMovieLister εξαρτάται από τη MovieFinder
private MovieFinder movieFinder;
// Χρησιμοποιείται κατασκευαστής, ώστε το Spring Container να κάνει inject ένα στιγμιότυπο Moviefinder.
public SimpleMovieLister(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
}
Το Setter-based DI πραγματοποιείται από το Container, καλώντας μεθόδους setters στα αντικείμενα, αφού καλέσουν πρώτα έναν κατασκευαστή χωρίς παραμέτρους ή μια μέθοδο-εργοστάσιο χωρίς παραμέτρους, για την αρχικοποίηση του αντικειμένου.
public class SimpleMovieLister {
// Η κλάση SimpleMovieLister εξαρτάται από τη MovieFinder
private MovieFinder movieFinder;
// Χρησιμοποιείται η μέθοδος setter, ώστε το Spring Container να κάνει inject ένα στιγμιότυπο Moviefinder.
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
}
Ξεκινώντας από την έκδοση 2.5, το Spring εισήγαγε ένα νέο τρόπο, να πραγματοποιήσουμε Dependency Injection με το annotation @Autowired. Αυτό το annotation επιτρέπει στο Spring να αποφασίζει και να κάνει inject τα συνεργαζόμενα beans σε ένα bean. Μπορεί να χρησιμοποιηθεί είτε σε πεδίο, είτε στον κατασκευαστή.
public class SimpleMovieLister {
// Το Spring κάνει inject ενα στιγμιότυπο movieFinder.
@Autowired
private MovieFinder movieFinder;
}