Зависимость - это ссылка на другой объект. Если объект класса B содержит ссылку на объект типа (класса или интерфейса) A, значит объект класса B имеет зависимость от объекта типа A.
Внедрение зависимости - получение объектом класса В ссылки на уже созданный (где то во вне) объект типа А.
Зависимость "ссылка на класс "- боле сильная, чем зависимость "ссылка на интерфейс".
public class A {
public void func(){
System.out.println("Hello World");
}
}
public class B {
private A a;
public B(A a){ // получение зависимости через конструктор
this.a = a;
}
public void useA(){
a.func(); // делегирование функционала другому объекту
}
}
public class App {
public static void main(String[] args) {
A a = new A();
B b = new B(a); // ручное внедрение зависимости
b.useA();
}
}
С помощью интерфейса зависимость от другого объекта уменьшается.
public interface IA {
void func();
}
public class A implements IA {
public void func(){
System.out.println("Hello World");
}
}
public class B {
private IA a;
public B(IA a){
this.a = a;
}
public void useA(){
a.func(); // делегирование функционала другому объекту
}
}
public class App {
public static void main(String[] args) {
IA a = new A();
B b = new B(a); // ручное внедрение зависимости
b.useA();
}
}
Зависимость от класса приводит к тому, что:
Зависимость от интерфейса считается менее сильной (относительно зависимости от класса) потому, что:
Создание зависимости в Spring:
import org.springframework.context.annotation.*;
import org.springframework.context.ApplicationContext;
public class App {
@Bean
public A a() {
return new A();
}
@Bean
public B b(A a) {
return new B(a);
}
public static void main (String[] args)
{
ApplicationContext context = new AnnotationConfigApplicationContext(App.class);
B b = context.getBean(B.class); // автоматическое внедрение зависимости
b.useA();
}
}
Внедрение автоматическое потому, что в явном виде нет создания объекта класса A и передачи ссылки на него в объект класса В. В Spring-фреймворке есть несколько правил автоматического сопоставления (разрешения) зависимостей. В данном случае работает правило:
если в контексте приложения имеется только один бин типа (класса) A, тогда любой бин, имеющий свойство или параметр конструктора типа A, будет зависеть именно от этого бина.