Страницы

Поиск по вопросам

вторник, 10 декабря 2019 г.

В чем разница между обычным программированием и программированием с использованием Spring?

#java #spring


Я понимаю как можно использовать Spring, но я до сих пор не могу понять то, о чём
везде так пишут: "Мы разрываем жёсткую связку между классами" и т.д., и т.п.

Но ведь мы и так жёстко всё прописываем либо в аннотациях, либо в *.xml, да и к тому
же в Main, когда пишем что-то вида:

Cat cat = context.getBean(Cat.class);
Dog dog = (Dog) context.getBean("dog");
Parrot parrot = context.getBean("parrot-kesha", Parrot.class);


Мы ведь и так тут всё жёстко прописали.

Также, Spring использует интерфейсы для ухода от жёсткой зависимости между классами.
Тогда что мне мешает без Spring сделать интерфейс IAnimals и в нём метод void voice();,

а потом, просто сделать:

class Cat implements IAnimals {
    publice void voice() {
        System.out.print("myau");
}}

class Dog implements IAnimals {
    publice void voice() {
        System.out.print("gav");
}}

class Parrot implements IAnimals {
    publice void voice() {
        System.out.print("kesha");
}}


???

Вот эту разницу между обычным программированием и программированием с использованием
Spring я не могу понять.
    


Ответы

Ответ 1



Вот вам реальный пример. Отправка sms на тестовом сервере и на рабочем. В коде который отправляет sms работаем с интерфейсом, а реализацию spring подставляет в зависимости от сервера. Если понадобится отправлять sms сообщение через другой сервис просто добавим новую реализацию, и не будем переписывать весь код, откуда отправляется sms. interface SmsService { void send(String to, String message); } @Service @Profile("development") class DevelopmentSmsService implements SmsService { public void send(String to, String message) { // печать сообщения в лог } } @Service @Profile("production") class ProductionSmsService implements SmsService { public void send(String to, String message) { // отправка сообщения через API нужного сервиса } } @Service class AnotherService { @Autowired SmsService smsService; public test() { // что-то делаем // отправляем sms через интерфейс, не заботясь о подробностях smsService.send(to, message); } } Вы рассматриваете слишком простые пример, где можно спокойно обойтись и без внедрения зависимостей. Но если бы у вас был проект на сотню тысяч классов, где один какой-нибудь UserRepository используется тысячу раз по всему проекту, вы бы поняли как это круто что spring подставил везде его реализацию вместо вас.

Ответ 2



Жесткая или не жесткая определяется тем, как вы будете использовать IAnimals. Для чего вы создали интерфейс? Для того чтобы иметь классы, которые его имплементируют. Если у вас несколько имплементаций, а вам нужна конкретная имплементация, то вы используете паттерн метода фактора или абстрактного фактора для создания экземпляра класса, который имплементирует этот интерфейс. Таким образом вы можете внедрять нежесткую связь в другие классы без использования Spring. У вас нет зависимостей между классами. Проблема появляется если вы будете устанавливать связи между объектами, и если эти связи должны быть нежесткие то вам всегда нужно четко знать где и когда, использовать и какую имплементацию. В общем если таких связей очень много, то вы будете морочить себе голову решая подобные проблемы. В конце концов вы поймете, что вам нужен Spring или какой нибудь другой контейнер, где вы будете определять зависимости с помощью конфигурации, независимо от кода их используемого. Более того, поскольку Spring берет на себя проблему создания бинов, то он еще и занимается менежментом. Что дает возможность интегрироваться в другие фреймворки.

Ответ 3



Основная фича Spring это его DI контейнер. Мы можем внедрять зависимости в бины, не задавая жестко тип. Вот Вы привели пример с интерфейсом Animal. Давайте разовьем немного тему. Допустим мы имеем вет. клинику и можем заставлять "говорить" любое животное. При этом нам абсолютно не важно какое это будет животное. Таким образом мы можем написать логику извлечения звука из животных один раз, а самих животных придумывать по ходу пьесы. И не придется править код вет. клиники, а лишь добавлять новых и новых Animal. @Component public class Clinic { private final List animals; @Autowired //ЕМНИП, в крайних версиях, даже этого делать уже не нужно public Clinic(List animals) { this.animals = animal; } public void doVoice() { for (Animal animal : animals) { animal.voice(); } } } public interface Animal { void voice(); } @Component public Cat implements Animal { @Override public void voice() { System.out.print("myau"); } } @Component public Dog implements Animal { @Override public void voice() { System.out.print("gav"); } } По поводу того, что мы в Spring все-равно жестко все задаем. Посмею с Вами не согласится. Да, в xml мы описывали бины, рассказывая Spring-у кто они, и что они. Теперь же Spring, при помощи аннотаций, сам может разобраться кто есть кто. Spring это уже не просто очередной фреймворк, это, можно сказать, промышленный стандарт. Советую к прочтению "Spring In Action" Крэйга Уолша, очень доступно товарищ объясняет.

Комментариев нет:

Отправить комментарий