Що робить Весняна рамка? Чи варто його використовувати? Чому або чому ні?


237

Отже, я починаю абсолютно новий проект на Java і розглядаю можливість використання Spring. Чому я розглядаю Весну? Тому що багато людей говорять мені, що я повинен використовувати Весна! Серйозно, щоразу, коли я намагався змусити людей пояснити, що саме таке Весна або що вона робить, вони ніколи не можуть дати мені прямої відповіді. Я перевірив вступи на сайті SpringSource, і вони або дуже складні, або по-справжньому орієнтовані на навчальний посібник, і жоден з них не дає мені гарного уявлення про те, навіщо мені користуватися ним, або як це полегшить моє життя. Іноді люди кидають навколо поняття "ін'єкція залежності", що просто бентежить мене ще більше, тому що я думаю, що я по-різному розумію, що означає цей термін.

У будь-якому випадку, ось трохи про мій фон та мою програму:

Деякий час розвивався в Java, роблячи розробки веб-сайтів. Так, я роблю тонну одиницю тестування. Щоб полегшити це, я зазвичай складаю (принаймні) дві версії методу: той, який використовує змінні екземпляри, і той, що використовує лише змінні, передані методу. Той, який використовує змінні екземпляри, викликає інший, постачаючи змінні екземпляра. Коли настає час тестування одиниць, я використовую Mockito для макетування об'єктів, а потім здійснюю виклики методу, який не використовує змінні екземпляри. Це те, що я завжди розумів як "ін'єкція залежності".

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

Я вже почав кодувати, і дуже хочу отримати демонстраційну версію, яку я можу робити по магазинах і бачити, чи хоче хтось інвестувати. Тож очевидно, що час є сутнісним. Я розумію, що у Spring є досить крива навчання, плюс, схоже, це потребує цілого ряду конфігурації XML, якої я, як правило, намагаюся уникати, як чуми. Але якщо це може полегшити моє життя і (особливо), якщо зробити це, може зробити розвиток і тестування швидше, я готовий кусати кулю і дізнатися Весну.

Тому будь-ласка. Навчіть мене. Чи варто використовувати Spring? Чому або чому ні?


10
Думаю, вам справді потрібно спробувати це на деякий час, щоб побачити, чи сподобалось вам і чи підходить воно для вашого проекту. Особисто я це ненавиджу.
Річард

1
Хоча ви можете використовувати XML або примітки; майте на увазі, що Весна приймає конвенцію щодо конфігураційного менталітету. Це не обов'язково контрольний список предметів , до яких потрібно звертатись.
Аарон Маківер

14
Хоча це правда, що це питання досить широке, я думаю, воно повинно залишатися відкритим. Я читав це як "Які переваги пропонує Весна для середнього проекту?", І це хороше питання.
sleske

1
Я настійно рекомендую прочитати мою улюблену технічну книгу: Spring in Action, Третє видання Craig Walls. Це чудове читання і змінить спосіб вашої програми.
alfredaday

4
Зважаючи на Enterprise Java, простіше відповісти на те, що весна не робить ...
m3th0dman

Відповіді:


108

Що робить Весняна рамка? Чи варто його використовувати? Чому або чому ні?

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

Це те, що я завжди розумів як "ін'єкція залежності".

Я б запропонував інше визначення:

"Сконструюйте свої об'єкти так, щоб вони покладалися на зовнішню силу, щоб забезпечити їм те, що їм потрібно, сподіваючись, що ці залежності завжди вводяться до того, як хтось попросить їх почати виконувати свою звичайну роботу".

Порівняйте це проти: "Кожен об'єкт несе відповідальність за те, щоб вийти на вулицю і знайти все, і все, що потрібно, коли він починається".

схоже, це потребує цілого ряду конфігурації XML

Ну, більшість матеріалів на основі XML (або на основі анотацій) розповідає про весняні речі, наприклад:

  • Коли хтось запитує "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пакету. Таким чином, ви можете перевіряти та змінювати змінні екземпляра, коли вам потрібно під час тестування.


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. Зауважте, що там не проводилося кастинг, а також не було необхідності оголошувати маршалки. Це все зроблено за вас.

Я можу назавжди запиратися про чудеса Весни, але, мабуть, найкраще зробити це спробувати простий код, де ви намагаєтеся зв’язати RESTful веб-сервіс, щоб викачати дані з введеного DAO, який підтримує транзакції.


4
так, RestTemplate досить приголомшливий. У мене є 100 рядків коду, які я можу викинути і замінити 2-3 рядками.
Кевін

11
До нітпіка: Вприскування в залежності також включає підхід, заснований на конструкторі. Вам не обов’язково мати сетерів.
Дарієн

28

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

Введення залежності, як це зазвичай розуміється (і реалізується Spring), означає, що залежності, які має клас (наприклад, джерело даних JDBC), не отримуються самим класом, а "вводяться" контейнером під час створення екземпляра. Отже, у вас немає двох версій кожного методу, який використовує джерело даних; натомість у вас є одна конфігурація введення залежності, де вводиться "справжній" джерело даних, та де вводиться макет. Або, якщо ін'єкція відбувається через конструктор або геттер, тестовий код може зробити ін'єкцію явно.

По-друге, Spring - це не просто введення залежності, хоча це її основна функціональність. Він також надає декларативні транзакції, планування роботи, аутентифікацію та купу інших функціональних можливостей (включаючи повноцінну веб-структуру MVC), яка може знадобитися. Є й інші рамки, які забезпечують той самий функціонал, але крім Spring, лише Java EE об'єднала їх.


ОП чудово розуміє DI
Базилевс

19

Чому ви хочете використовувати Spring, ви можете прочитати її на веб-сторінці http://www.wrox.com/WileyCDA/Section/Why-Use-the-Spring-Framework-.id-130098.html

Підсумовуючи:

  • Програми J2EE, як правило, містять надмірну кількість "сантехнічного" коду. Багато оглядів коду неодноразово виявляють високу частку коду, який нічого не робить: код пошуку JNDI, об’єкти передачі, спробуйте / ловити блоки для придбання та випуску ресурсів JDBC. . . . Написання та підтримання такого сантехнічного коду доводить значну витрату ресурсів, які слід зосередити на діловій сфері програми.

  • У багатьох програмах J2EE використовується модель розподіленої об'єкта, коли це недоцільно. Це одна з головних причин надмірного дублювання коду та коду. Це також концептуально неправильно у багатьох випадках; Внутрішньо розподілені програми складніші, ніж сумісні програми, і часто набагато менш ефективні. Звичайно, якщо ваші вимоги бізнесу диктують розподілену архітектуру, вам потрібно реалізувати розподілену архітектуру та прийняти компроміс, який виникає (і Spring пропонує функції, що допомагають у таких сценаріях). Але ви не повинні робити це без вагомих причин.

  • Модель компонентів EJB є надмірно складною. EJB був задуманий як спосіб зменшення складності при впровадженні бізнес-логіки в додатки J2EE; це не вдалося досягти цієї мети на практиці.

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

  • Багато "моделей дизайну J2EE" насправді не є моделями дизайну, а є обрізними для технологічних обмежень. Надмірне використання дистрибуції та використання складних API, таких як EJB, породили багато сумнівних моделей дизайну; важливо розглянути ці питання критично і шукати більш прості, продуктивні підходи.

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

  • Деякі технології J2EE просто не вдалися. Основний правопорушник тут - квасоля, яка виявилася недостатньо небезпечною для продуктивності та обмеженості орієнтації на об'єкти.


13

Раніше ми писали прості, ефективні, швидкі програми та веб-сервіси, використовуючи лише основні Java, сервлети та JSP, html та xml, JDBC API. Це було досить добре; JUnit був хорошим інструментом для тестування. Ми легко відпочили, що наш код працював.

Hibernate запропонував спростити SQL та включити істинне відображення таблиць баз даних з об’єктами Java, що дозволило відображати ієрархічні зв'язки в картографічному відношенні об'єктів або ORM, як ми його називаємо. Я любив це. Тим більше, що нам не довелося відображати ResultSet назад в об'єкт Java або тип даних.

Струц прийшов, щоб додати шаблон контролера перегляду моделі до наших веб-додатків, це було добре.

EJB були величезними накладними головами, і біль та анотації зробили код схожим на курячу подряпину, і тепер Весна зародилася на нас невинних людей. Мені просто здається перестаратися.

Наприклад, ми тепер пакуємо наш простий jdbc URL, користувач, переходимо спочатку в jdbc.properties, потім у сплячі властивості другий, а потім у весняні боби втретє!

Попри все, врахуйте, що зв’язок там, де вам це потрібно, насправді так само просто, як показано нижче в чистому Java. Це те, що ми насправді робимо після того, як пройдемо всю цю гарячу атмосферу разом із Spring:

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

Це саме по собі пояснює, що його великий круглий і обертаючий круглий і круглий, щоб робити просту річ швидко і легко, без інших великих переваг насправді. Це як би обернути тонни і тонни подарункового паперу навколо крихітного приємного подарунка, який все-таки ви справді зберігаєте.

Інший приклад - пакетне оновлення. З Spring він складається з декількох класів, інтерфейсів, перш ніж використовувати JdbcTemplate для пакетного оновлення. З простим jdbc його просто:

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

Неможливо отримати простіше чи швидше.

Я не підтримую ці рамки. Вибачте. Хто на землі хоче ін'єкції кожного разу, коли їм щось потрібно?


6
цей код простий, але де визначено обробку транзакцій і як ви тестуєте його? Обидві речі спрощуються до весни. Крім того, ваш Java-код прямо прив’язаний до db-з'єднання, якщо ви не зберігаєте URL-адреси та паролі з'єднання зовні, це також буде спрощено до весни.
NimChimpsky

+1 для цієї відповіді, щоб звернутися до вищевказаного коментаря, людина використовує власні шаблони дизайну легкої ваги (GOF), синглтон для об'єднання з'єднань, проксі-клас, який надає sql (рядок) та значення (масив) до об’єкта бази даних (який метод , залежить від методу http), dbobject обробляє об'єднання з'єднань, транзакції тощо, виконуючи запит з подальшим випуском. Використання одного об'єкта у всіх модулях, нікому не потрібен надмірний код пластини котла. бонусний бал із встановленням одиничних тестів на клас проксі та dbobject.
користувач2727195

Перевірте Spring-Data-JPA, хоча! Анотуйте pojo в сутність, реалізуйте інтерфейс та визначте підписи методів за допомогою розумних імен, таких як findHammerByWeight (), і весна реалізує методи для вас, надаючи вам ін'єкційний сховище, яке ви можете використовувати у всіх інших класах служб чи контролерів. .
mancini0

13

Що робить Весняна рамка?

Весна - це сьогодні не тільки те, що було відоме як простий каркас, це повноцінна екосистема.

Теми, охоплені весняною екосистемою:

  • Весняна рамка (наприклад, впорскування залежності, AOP ...)

  • Весняна хмара

  • Весняні дані

  • Весна безпека

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

  • Весна Соціальна

Дивіться тут для повного висвітлення екосистеми. Можна вибирати проекти вишень, щоб ви могли використовувати Google Guice для DI та, наприклад, Spring Security для обробки речей, пов’язаних із безпекою. ВАМ не потрібно купувати цілу екосистему.

Сама рамка Весна сьогодні охоплює в основному

  • Ін'єкційна залежність

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

  • Весняний веб-додаток MVC та рамка веб-сервісу RESTful

  • Основна підтримка JDBC, JPA, JMS

Джерело spring.io

Загалом, можна сказати, що Spring - це сукупність реалізованих шаблонів та практик у коді, які можуть допомогти покращити або прискорити цикл розробки додатків.

Для того, що саме воно (основна рамка) найбільше відоме - це можливості в галузі введення залежності . Сама пружина має, що називається, інверсія керуючого контейнера або короткий контейнер IoC або навіть коротший контейнер (для якого "пружина" іноді використовується синонімом).

Що таке ін'єкційна залежність?

Введення залежності залежить від того, що ваш об'єкт отримує кожну залежність від інших об'єктів через зовнішній механізм.

Скажімо, у вас є машина, типовий спосіб її реалізації:

public class Car {

    Engine e;

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

}

Об'єкт автомобіля залежить від двигуна. Оскільки двигун реалізований як член автомобіля, його неможливо замінити, наприклад, для тестового двигуна.

Тепер вводиться ін'єкційна залежність :

public class Car {

    Engine e;

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

}

Після цього ви можете перемикати двигуни. Те, що ви бачите вище, називається конструкторним вприском . Існують і інші типи, наприклад, сетер- ін'єкція або метод -ін'єкція. Як Вам допомагає Весна в цьому? Весна дозволяє йому відзначати компоненти, які вводяться з анотацією, @Autowiredі проводить проводку об'єкта, що ін'єктується, автоматично - цілком ймовірно, що компонент, який ви хочете ввести, має самі залежності. Ін'єкційні вироби - так би мовити - позначаються через@Component

public class Car {

    Engine e;

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

}

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

Чи варто використовувати Spring? Чому або чому ні?

Оскільки весна не дуже нав'язлива і пропонує багато посібників, то вам слід розглянути можливість використання весни. Спеціально для нових проектів Spring Boot дуже привабливий. start.spring.io пропонує простий у використанні point'n'click -інтерфейс для створення шаблону проекту для початку роботи. Можна навіть 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  |
+-----------------+-----------------------------------------+

...

З іншого боку, такі рамки, як іскра або дроп-майстер, також пропонують хорошу вихідну точку для швидкого створення веб-додатків.


1
Дуже інформативна відповідь!
GOXR3PLUS

Погоджена, дуже хороша відповідь. ОП, я співчуваю вам. У мене також було декілька людей, які показують мені весняні демонстрації, де вони "спрощують" код, додаючи XML-файл та два шари непрямості, щоб вони могли викликати конструктора в класі :) Вам дійсно просто потрібно зануритися або перейти до насправді хороша презентація, і врешті-решт стане зрозуміло, де переваги та недоліки
Адам Хьюз

4

Це рамка, написана на Java, яка містить багато речей, щоб зробити ваше веб-додаток функціональним (наприклад, підтримка інтернаціоналізації). Це також дає хороший спосіб структурувати додаток по шарах. Використовуйте його, це заощадить вам багато часу в довгостроковій перспективі.

Хороша книга, щоб дізнатися про весну: Експертна весна MVC та веб-потік

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.