Что делает среда Spring? Должен ли я использовать это? Почему или почему нет?

237

Итак, я начинаю новый проект на Java и собираюсь использовать Spring. Почему я рассматриваю весну? Потому что многие люди говорят мне, что я должен использовать Spring! Серьезно, каждый раз, когда я пытался заставить людей объяснить, что такое Spring или что он делает, они никогда не могли дать мне прямой ответ. Я проверил вступления на сайте SpringSource, и они либо очень сложны, либо ориентированы на учебники, и ни одно из них не дает мне хорошего представления о том, почему я должен его использовать или как это облегчит мою жизнь. Иногда люди используют термин «инъекция зависимости», что еще больше смущает меня, потому что я думаю, что у меня другое понимание того, что означает этот термин.

В любом случае, вот немного о моем прошлом и моем приложении:

Некоторое время занимался разработкой на Java, занимался веб-разработкой. Да, я делаю тонну модульного тестирования. Чтобы облегчить это, я обычно делаю (как минимум) две версии метода: одну, которая использует переменные экземпляра, и другую, которая использует только те переменные, которые передаются в метод. Тот, который использует переменные экземпляра, вызывает другой, предоставляя переменные экземпляра. Когда приходит время модульного тестирования, я использую Mockito для макетирования объектов, а затем вызываю метод, который не использует переменные экземпляра. Это то, что я всегда понимал под «внедрением зависимости».

Мое приложение довольно простое, с точки зрения CS. Небольшой проект, 1-2 разработчиков для начала. В основном это операции типа CRUD с множеством поисковых запросов. В основном, это набор веб-сервисов RESTful, а также веб-интерфейс и, в конечном итоге, некоторые мобильные клиенты. Я подумываю о создании внешнего интерфейса в прямом HTML / CSS / JS / JQuery, поэтому никаких реальных планов по использованию JSP нет. Использование Hibernate в качестве ORM и Джерси для реализации веб-сервисов.

Я уже начал программировать, и я действительно хочу получить демо, где я могу ходить по магазинам и посмотреть, хочет ли кто-нибудь инвестировать. Очевидно, что время имеет существенное значение. Я понимаю, что у Spring довольно крутая кривая обучения, и, похоже, он требует целой связки конфигурации XML, которую я обычно стараюсь избегать, как чумы. Но если это может сделать мою жизнь проще и (особенно), если это может сделать разработку и тестирование быстрее, я готов прикусить пулю и изучить Spring.

Так пожалуйста. Просвети меня. Должен ли я использовать Spring? Почему или почему нет?

хладнокровие
источник
10
Я думаю, вам действительно нужно попробовать его на некоторое время, чтобы увидеть, нравится ли он вам и подходит ли он для вашего проекта. Лично я ненавижу это.
Ричард
1
Пока вы можете использовать XML или аннотации; имейте в виду, что Spring принимает соглашение о конфигурации менталитета. Это не обязательно контрольный список предметов, к которым вы должны обратиться.
Аарон Макивер
14
Хотя это правда, что этот вопрос довольно широкий, я думаю, что он должен оставаться открытым. Я прочитал его как «Какие преимущества предлагает Spring для проекта среднего размера?», И это хороший вопрос.
слеске
1
Я настоятельно рекомендую прочитать мою любимую техническую книгу «Весна в действии», третье издание Крейга Уоллса. Это отличное чтиво, которое изменит способ программирования.
Alfredaday
4
Учитывая Enterprise Java, проще ответить на то, что Spring не делает ...
m3th0dman

Ответы:

108

Что делает среда Spring? Должен ли я использовать это? Почему или почему нет?

Spring - это фреймворк, который помогает вам соединять различные компоненты. Это наиболее полезно в тех случаях, когда у вас много компонентов, и вы можете решить объединить их по-разному или хотите упростить замену одного компонента на другой в зависимости от различных настроек или сред.

Это то, что я всегда понимал под «внедрением зависимости».

Я бы предложил другое определение:

«Спроектируйте ваши объекты так, чтобы они полагались на внешние силы, чтобы обеспечить их тем, что им нужно, с надеждой, что эти зависимости всегда вводятся, прежде чем кто-нибудь попросит их начать выполнять свою обычную работу».

Сравните это со словами: «Каждый объект отвечает за выход и поиск всего и всего, что ему нужно при запуске».

похоже, это требует целой связки конфигурации XML

Ну, большинство XML (или основанных на аннотациях) материалов рассказывают о Spring, например:

  • Когда кто-то запрашивает «HammerStore», я хочу, чтобы вы создали экземпляр example.HammerStoreи вернули его. Кэшируйте экземпляр в следующий раз, так как должен быть только один магазин.
  • Когда кто-то запрашивает «SomeHammer», я хочу, чтобы вы спросили себя о «HammerStore» и вернули результат метода магазина makeHammer(). Вы не кэшировать этот результат.
  • Когда кто-то запрашивает «SomeWrench», я хочу, чтобы вы создали экземпляр. example.WrenchImplИспользуйте параметр конфигурации gaugeAmountи поместите его в setWrenchSize()свойство экземпляра . Не кэшируйте результат.
  • Когда кто-то просит «LocalPlumber», я хочу, чтобы вы создали экземпляр example.PlumberImpl. Поместите строку «Pedro» в его setName()метод, вставьте «SomeHammer» в его setHammer()метод и вставьте «SomeWrench» в его setWrench()метод. Верните результат и кешируйте результат на потом, так как нам нужен только один сантехник.

Таким образом, Spring позволяет подключать компоненты, маркировать их, управлять их жизненными циклами / кэшированием и изменять поведение в зависимости от конфигурации.

Чтобы облегчить [тестирование], я обычно делаю (как минимум) две версии метода: одну, которая использует переменные экземпляра, и другую, которая использует только те переменные, которые передаются в метод.

Это звучит как много накладных расходов, но для меня это не очень полезно. Вместо этого сделайте так, чтобы переменные вашего экземпляра имели protectedвидимость пакета или , и найдите модульные тесты в том же com.mycompany.whateverпакете. Таким образом, вы можете проверять и изменять переменные экземпляра, когда захотите во время тестирования.

Darien
источник
65

Во-первых, что такое внедрение зависимостей?

Просто. У вас есть класс, у него есть приватное поле (установлено на ноль), и вы объявляете открытый сеттер, который предоставляет значение для этого поля. Другими словами, зависимость класса (поля) вводится внешним классом (через установщик). Вот и все. Ничего волшебного.

Во-вторых, Spring можно использовать без XML (или очень мало)

Если вы погрузитесь в Spring 3.0.5.GA или выше, вы можете использовать поддержку внедрения зависимостей из JDK6 +. Это означает , что вы можете подключить до зависимостей , используя @Componentи @Resourceаннотации.

Зачем вообще использовать Spring?

Очевидно, что внедрение зависимостей способствует очень простому модульному тестированию, поскольку во всех ваших классах есть сеттеры для важных зависимостей, и их можно легко смоделировать с помощью вашей любимой инфраструктуры для обеспечения требуемого поведения.

Помимо этого, Spring также предоставляет множество шаблонов, которые действуют как базовые классы, чтобы сделать использование стандартных технологий JEE легким для работы. Например, JdbcTemplate хорошо работает с JDBC, JpaTemplate хорошо работает с JPA, JmsTemplate делает JMS довольно простым. RestTemplate просто удивителен своей простотой. Например:

RestTemplate restTemplate = new RestTemplate();
MyJaxbObject o = restTemplate.getForObject("https://secure.example.org/results/{param1}?param2={param2}",MyJaxbObject.class,"1","2");

и вы сделали. Параметры вводятся, и вам просто нужно предоставить аннотации JAXB для MyJaxbObject. Это не займет много времени, если вы автоматически сгенерировали их из XSD с помощью плагина Maven JAXB. Обратите внимание, что там не было кастинга и не было необходимости объявлять маршала. Это все сделано для вас.

Я мог бы навсегда поговорить о чудесах Spring, но, возможно, лучше всего попробовать простой скачок кода, когда вы пытаетесь подключить веб-сервис RESTful для откачки данных из внедренного DAO, который поддерживает транзакции.

Гэри Роу
источник
4
да RestTemplate довольно круто. У меня есть около 100 строк кода, которые я могу выбросить и заменить на 2-3 строки.
Кевин
11
Для придирки: Dependency Injection также включает в себя конструкторский подход. Вам не обязательно иметь сеттеров.
Дариен
28

Прежде всего, ваше понимание внедрения зависимости не является в корне неверным, но весьма отличается от того, что имеет в виду большинство людей, когда они используют этот термин. То, что вы описываете, является довольно странным и нетрадиционным способом достижения тестируемости. Я бы посоветовал вам отойти от этого, так как другие разработчики будут весьма озадачены таким кодом.

Внедрение зависимостей, как его обычно понимают (и реализует Spring), означает, что зависимости, которые имеет класс (например, источник данных JDBC), не выбираются самим классом, а «внедряются» контейнером при создании экземпляра. Таким образом, у вас нет двух версий каждого метода, использующего источник данных; вместо этого у вас есть одна конфигурация внедрения зависимостей, в которую внедряется «реальный» источник данных, и одна, где вводится фиктивный источник. Или, если внедрение происходит через конструктор или получатель, тестовый код может выполнить внедрение явно.

Во-вторых, Spring - это не просто внедрение зависимостей, хотя это его основная функциональность. Он также предоставляет декларативные транзакции, планирование заданий, аутентификацию и множество других функций (включая полноценную веб-инфраструктуру MVC), которые могут вам понадобиться. Существуют и другие фреймворки, предоставляющие такую ​​же функциональность, но кроме Spring, только в Java EE они интегрированы.

Майкл Боргвардт
источник
ОП прекрасно понимает ДИ
Васильев
19

Почему вы хотите использовать Spring, вы можете прочитать на http://www.wrox.com/WileyCDA/Section/Why-Use-the-Spring-Framework-.id-130098.html

В итоге :

  • Приложения J2EE, как правило, содержат чрезмерное количество «соединительного» кода. Во многих обзорах кода неоднократно обнаруживается большая доля кода, который ничего не делает: код поиска JNDI, объекты Transfer Object, блоки try / catch для получения и освобождения ресурсов JDBC. , , , Написание и сопровождение такого программного кода доказывает значительную утечку ресурсов, которые должны быть сосредоточены на бизнес-сфере приложения.

  • Многие приложения J2EE используют распределенную объектную модель, где это неуместно. Это одна из основных причин избыточного кода и дублирования кода. Это также концептуально неправильно во многих случаях; Внутренне распределенные приложения являются более сложными, чем совместные приложения, и часто гораздо менее производительными. Конечно, если ваши бизнес-требования диктуют распределенную архитектуру, вам нужно реализовать распределенную архитектуру и принять компромисс, который возникает (и Spring предлагает функции, помогающие в таких сценариях). Но вы не должны делать это без веской причины.

  • Компонентная модель EJB является чрезмерно сложной. EJB был задуман как способ уменьшения сложности при реализации бизнес-логики в приложениях J2EE; она не достигла этой цели на практике.

  • EJB перегружен EJB был разработан для внутренних распределенных транзакционных приложений. Хотя почти все нетривиальные приложения являются транзакционными, распределение не должно быть встроено в базовую модель компонентов.

  • Многие «шаблоны проектирования J2EE» на самом деле являются не шаблонами проектирования, а обходными решениями для технологических ограничений. Злоупотребление распространением и использование сложных API, таких как EJB, породили много сомнительных шаблонов проектирования; важно критически изучить их и найти более простые, более продуктивные подходы.

  • Приложения J2EE сложно тестировать. J2EE API, и особенно, компонентная модель EJB, были определены до того, как началось гибкое движение. Таким образом, их дизайн не учитывает простоту модульного тестирования. С помощью как API, так и неявных контрактов на удивление сложно тестировать приложения на основе EJB и многих других API J2EE вне сервера приложений. Тем не менее, модульное тестирование вне сервера приложений необходимо для обеспечения высокого охвата тестированием и воспроизведения многих сценариев отказов, таких как потеря подключения к базе данных. Также очень важно обеспечить быстрое выполнение тестов в процессе разработки или сопровождения, сводя к минимуму непроизводительное время ожидания повторного развертывания.

  • Некоторые технологии J2EE просто потерпели неудачу. Основным нарушителем в данном случае являются бины сущностей, которые оказались весьма катастрофическими для производительности и в своих ограничениях на ориентацию объектов.

Rudy
источник
13

Раньше мы писали простые, эффективные, быстрые приложения и веб-сервисы, используя только основные Java, Servlets и JSP, html и xml, JDBC API. Это было достаточно хорошо; JUnit был хорошим инструментом для тестирования. Мы успокоились, что наш код работал.

Hibernate пришел к тому, чтобы упростить SQL и обеспечить истинное отображение таблиц базы данных с Java-объектами, позволяя отражать иерархические отношения в Object Relations Mapping или ORM, как мы его называем. Я люблю это. Особенно из-за того, что нам не пришлось отображать ResultSet обратно в Java-объект или тип данных.

Компания Struts добавила шаблон Model View Controller в наши веб-приложения, это было хорошо.

EJB были огромными накладными расходами и болью, а аннотации делали код похожим на куриную царапину, и теперь Spring нас окружили невинные люди. Мне кажется, это перебор.

Например, теперь мы упаковываем наш простой jdbc url, user, сначала в jdbc.properties, затем в свойства hibernate, а затем в bean-компоненты Spring в третий раз!

В отличие от всего этого, подумайте о том, чтобы получить соединение там, где оно вам нужно, на самом деле так же просто, как показано ниже на чистой Java, и именно это мы и делаем, пройдя весь этот горячий воздух с Spring:

Connection connection = DriverManager.getConnection(url, user, pass);

Само по себе это говорит о том, что это большой круг и обход кругов, чтобы делать простую вещь быстро и легко без других больших выгод на самом деле. Это похоже на упаковку тонны и тонны подарочной бумаги вокруг крошечного приятного подарка, и это все, что вы на самом деле храните.

Другой пример - пакетное обновление. В Spring это запутано, включая довольно много классов и интерфейсов, прежде чем вы сможете использовать JdbcTemplate для пакетного обновления. С простым jdbc это просто:

Statement statement = connection.createStatement();
statement.addBatch(sqlquery);
statement.executeBatch();

Не может быть проще или быстрее, чем это.

Я не поддерживаю эту структуру. Сожалею. Кто на земле хочет делать уколы каждый раз, когда им что-нибудь нужно?

Ума
источник
6
этот код прост, но где определена ваша обработка транскрипции и как вы ее тестируете? Обе вещи упрощаются к весне. Кроме того, ваш java-код напрямую связан с подключением к БД, если вы не сохраняете внешние URL-адреса и пароли подключения, это также упрощается весной.
НимЧимпский
+1 за этот ответ, чтобы ответить на комментарий выше, человек использует ваши собственные легкие шаблоны проектирования (GOF), синглтон для пула соединений, прокси-класс, который предоставляет sql (строку) и значения (массив) для объекта базы данных (какой метод , зависит от метода http), dbobject обрабатывает пул соединений, транзакции и т. д., выполняя запрос с последующим освобождением. Один объект используется во всех модулях, никому не нужен избыточный код котельной плиты. Бонусный пункт с настройкой юнит-тестов на прокси-класс и dbobject.
user2727195
Проверьте Spring-Data-JPA, хотя! Аннотируйте pojo в сущности, реализуйте интерфейс и определяйте сигнатуры методов, используя разумные имена, такие как findHammerByWeight (), и Spring реализует методы для вас, предоставляя вам инъекционный репозиторий, который вы можете использовать во всех других ваших классах бизнес-сервисов или контроллеров ,
mancini0
13

Что делает среда Spring?

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

Темы, охватываемые весенней экосистемой:

  • Spring Framework (например, Dependency Injection, AOP ...)

  • Весеннее Облако

  • Spring Data

  • Spring Security

  • Весенняя партия

  • Spring Social

Смотрите здесь для полного охвата экосистемы. Можно выбирать проекты по вишне, чтобы вы могли использовать Google Guice для DI и, например, Spring Security для управления безопасностью. Вы не должны покупать всю экосистему.

Сама Spring-Framework сегодня охватывает в основном

  • Внедрение зависимости

  • Аспектно-ориентированное программирование, включая декларативное управление транзакциями Spring

  • Веб-приложение Spring MVC и платформа веб-сервиса RESTful

  • Основополагающая поддержка JDBC, JPA, JMS

Источник spring.io

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

Из-за того, что он (ядро-фреймворк) наиболее известен своими возможностями в области внедрения зависимостей . Сама Spring имеет то, что называется инверсией управляющего контейнера или коротким контейнером IoC, или даже более коротким контейнером (для которого «пружина» иногда используется как синоним).

Что такое внедрение зависимостей?

Внедрение зависимостей означает, что ваш объект получает каждую зависимость от других объектов посредством внешнего механизма.

Скажем, у вас есть машина, типичный способ ее реализации:

public class Car {

    Engine e;

    public Car() { 
        e = new Engine(); 
    }

}

Объект автомобиля зависит от двигателя. Поскольку двигатель реализован как элемент автомобиля, его нельзя заменить, например, на испытательный двигатель.

Теперь вводится зависимость :

public class Car {

    Engine e;

    public Car(Engine e) { 
        this.e = e; 
    }

}

После этого вы можете переключать двигатели. То, что вы видите выше, называется инжектором конструктора . Есть и другие типы, например, setter -injection или method -injection. Как Spring помогает вам в этом? Spring позволяет помечать компоненты для @Autowiredдобавления аннотацией и автоматически выполняет подключение объекта, на который наложили инъекцию, - вполне вероятно, что компонент, который вы хотите добавить, имеет свои зависимости. Injectables - так сказать - отмечены через@Component

public class Car {

    Engine e;

    @Autowired
    public Car(Engine e) { 
        this.e = e; 
    }

}

Но это только одна из многих возможностей, которые предлагает Spring.

Должен ли я использовать Spring? Почему или почему нет?

Поскольку Spring не очень навязчив и предлагает множество вспомогательных средств, вы должны рассмотреть возможность использования Spring. Spring Boot специально для новых проектов очень привлекателен. start.spring.io предлагает простой в использовании point'n'click -INTERFACE для создания шаблона проекта , чтобы начать работу. Можно даже использовать curlдля получения шаблона:

curl start.spring.io

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/

:: Spring Initializr ::  https://start.spring.io

This service generates quickstart projects that can be easily customized.
Possible customizations include a project's dependencies, Java version, and
build system or build structure. See below for further details.

The services uses a HAL based hypermedia format to expose a set of resources
to interact with. If you access this root resource requesting application/json
as media type the response will contain the following links:
+-----------------+-----------------------------------------+
| Rel             | Description                             |
+-----------------+-----------------------------------------+
| gradle-build    | Generate a Gradle build file            |
| gradle-project  | Generate a Gradle based project archive |
| maven-build     | Generate a Maven pom.xml                |
| maven-project * | Generate a Maven based project archive  |
+-----------------+-----------------------------------------+

...

С другой стороны, фреймворки, такие как spark или dropwizard, предлагают хорошую отправную точку для быстрого создания веб-приложений.

Томас Джанк
источник
1
Очень информативный ответ!
GOXR3PLUS
Согласен, очень хороший ответ. ОП, я вам сочувствую. У меня также было несколько человек, которые демонстрировали мне демонстрации Spring, где они «упрощали» код, добавляя XML-файл и два уровня косвенности, чтобы они могли вызывать конструктор в классе :) Вам действительно нужно просто погрузиться или перейти к действительно хорошая презентация, и в конечном итоге станет ясно, где преимущества и недостатки
Адам Хьюз
4

Это фреймворк, написанный на Java, со множеством вещей, включающих в себя функциональность вашего веб-приложения (например, поддержка интернационализации). Это также обеспечивает хороший способ структурировать ваше приложение по слоям. Используйте его, это сэкономит вам много времени в долгосрочной перспективе.

Хорошая книга для изучения Spring: Expert Spring MVC и Web Flow

Бернард
источник