Основная концепция внедрения зависимостей - насколько я понимаю - это практика «проектирования интерфейсов», позволяющая сделать зависимые компоненты слабосвязанными друг с другом. Однако я видел много систем, разработанных с использованием Spring, которые, на мой взгляд, нарушают эту концепцию [и Spring Container допускает это на уровне синтаксиса]. Я начинаю сомневаться в своих знаниях / понимании концепции внедрения зависимостей после того, как увидел такой код / реализацию.
Я регулярно вижу, как компоненты автоматически подключаются друг к другу с их конкретной реализацией, пример того, что я имею в виду:
@RestController
public class MyRestController {
@AutoWired
private MyServiceOne serviceOne;
// .. rest of the code if the rest controller here ...
}
@Service
public class MyServiceOne {
@Autowired
private MyRepository repo;
// rest of code of the service here
}
как видите, MyServiceOne - это конкретный класс, а не интерфейс, и Spring Framework с этим согласен. В классе «@Configuration» не нужно предоставлять метод «@Bean» где-нибудь, чтобы внедрить правильный конкретный тип класса [поскольку @service уже является конкретным классом].
Итак, для любого изменения / настройки на уровне обслуживания [внедренная зависимость в контроллере] мне придется изменить следующую строку в контроллере:
@AutoWired
private MyServiceOne serviceOne; //change this to be another service class, or a service class that extends it
и это НЕ является слабым сцеплением! [или нет?] на мой взгляд, если мы собираемся использовать Spring DI таким образом, лучше НЕ использовать его вообще! в памяти приложения создается множество зависимостей maven / Gradle и объектов времени выполнения!
Мне интересно, чего-то не хватает в моем понимании того, как внедрение зависимостей является концепцией / или как Spring Handle Dependency Injection?
ценю ваше руководство!
Использование интерфейса обычно является наилучшей практикой, и вам обычно следует предпочесть его в своем собственном коде (вместе с внедрением конструктора вместо этого внедрения поля), но абсурдный пуристизм в отношении того, что разрешено, будет контрпродуктивным.
Например, я работаю с Amazon DynamoDB, и мне нужно внедрить экземпляр класса DynamoDB
. Я бы действительно предпочел иметь возможность внедрять интерфейс, но SDK Amazon не предоставляет его, и возможность внедрить настроенный экземпляр класса по-прежнему намного лучше, чем ничего не вводить.
Точно так же в Spring Boot нередко внедряют bean-компоненты @ConfigurationProperties
, которые в основном представляют собой структурные объекты POJO без какой-либо логики. В этом случае определение интерфейса было бы пустой тратой времени, но возможность вводить bean-компоненты по (конкретному) типу чрезвычайно полезна.