Co robi środowisko Spring? Czy powinienem tego użyć? Dlaczego lub dlaczego nie?

236

Zaczynam nowy projekt w Javie i zastanawiam się nad Springem. Dlaczego rozważam wiosnę? Ponieważ wiele osób mówi mi, że powinienem użyć wiosny! Poważnie, za każdym razem, gdy próbuję nakłonić ludzi do wyjaśnienia, czym dokładnie jest Wiosna i co ona robi, nigdy nie mogą dać mi prostej odpowiedzi. Sprawdziłem wprowadzenie na stronie SpringSource i są one albo bardzo skomplikowane, albo koncentrują się na samouczkach, i żadne z nich nie daje mi pojęcia, dlaczego powinienem z niego korzystać ani w jaki sposób ułatwi to moje życie. Czasami ludzie rzucają się wokół terminu „wstrzyknięcie zależności”, co jeszcze bardziej mnie dezorientuje, ponieważ myślę, że inaczej rozumiem, co to pojęcie oznacza.

Tak czy inaczej, oto trochę o moim pochodzeniu i mojej aplikacji:

Od jakiegoś czasu rozwijam się w Javie, robiąc back-endowe tworzenie stron internetowych. Tak, przeprowadzam mnóstwo testów jednostkowych. Aby to ułatwić, zazwyczaj tworzę (przynajmniej) dwie wersje metody: jedną, która wykorzystuje zmienne instancji, i jedną, która wykorzystuje tylko zmienne przekazane do metody. Ten, który używa zmiennych instancji, wywołuje drugi, podając zmienne instancji. Kiedy przychodzi czas na test jednostkowy, używam Mockito, aby wyśmiewać obiekty, a następnie wywołuję metodę, która nie używa zmiennych instancji. To właśnie zawsze rozumiałem jako „zastrzyk zależności”.

Moja aplikacja jest dość prosta z punktu widzenia CS. Mały projekt, od 1 do 2 programistów. Przeważnie operacje typu CRUD z wrzuconą wyszukiwarką. Zasadniczo kilka usług sieciowych RESTful oraz interfejs internetowy, a następnie niektórzy klienci mobilni. Zastanawiam się nad stworzeniem front-endu w prostym HTML / CSS / JS / JQuery, więc nie ma prawdziwych planów korzystania z JSP. Używanie Hibernacji jako ORM i Jersey do implementacji usług sieciowych.

Już zacząłem pisać kodowanie i bardzo chcę uzyskać wersję demonstracyjną, którą mogę kupić i sprawdzić, czy ktoś chce zainwestować. Oczywiście czas jest najważniejszy. Rozumiem, że Spring ma dość krzywą uczenia się, a ponadto wygląda na to, że wymaga całej konfiguracji XML, czego zwykle staram się unikać jak zarazy. Ale jeśli może to ułatwić moje życie i (zwłaszcza) sprawić, że rozwój i testowanie będą szybsze, jestem gotów ugryźć kulę i nauczyć się Wiosny.

Więc proszę. Naucz mnie. Czy powinienem używać wiosny? Dlaczego lub dlaczego nie?

sangfroid
źródło
10
Myślę, że naprawdę powinieneś wypróbować go przez chwilę, aby zobaczyć, czy ci się podoba i czy nadaje się do twojego projektu. Osobiście nienawidzę tego.
Richard
1
Chociaż możesz używać XML lub adnotacji; pamiętaj, że Spring ma konwencję dotyczącą mentalności konfiguracji. Niekoniecznie musi to być lista kontrolna elementów, które należy rozwiązać.
Aaron McIver
14
Chociaż prawdą jest, że to pytanie jest dość szerokie, myślę, że powinno pozostać otwarte. Przeczytałem to jako „Jakie korzyści oferuje Spring dla średniego projektu?”, I to jest dobre pytanie.
sleske,
1
Bardzo polecam przeczytanie mojej ulubionej książki technicznej: Spring in Action, Third Edition Craig Walls. To świetna lektura i zmieni sposób programowania.
alfredaday
4
Biorąc pod uwagę Enterprise Java, łatwiej jest odpowiedzieć na to, czego nie robi Spring ...
m3th0dman,

Odpowiedzi:

108

Co robi środowisko Spring? Czy powinienem tego użyć? Dlaczego lub dlaczego nie?

Spring to framework, który pomaga łączyć ze sobą różne elementy. Jest to najbardziej przydatne w przypadkach, gdy masz wiele komponentów i możesz zdecydować o połączeniu ich na różne sposoby, lub chcesz ułatwić wymianę jednego komponentu na inny, w zależności od różnych ustawień lub środowisk.

To właśnie zawsze rozumiałem jako „zastrzyk zależności”.

Sugerowałbym inną definicję:

„Zaprojektuj swoje obiekty w taki sposób, aby polegały na sile zewnętrznej, która dostarczy im to, czego potrzebują, z oczekiwaniem, że te zależności są zawsze wprowadzane, zanim ktokolwiek poprosi je o rozpoczęcie zwykłej pracy”.

Porównaj to z: „Każdy obiekt odpowiada za wyjście i znalezienie wszystkiego i wszystkich, których potrzebuje na starcie”.

wygląda na to, że wymaga całej konfiguracji XML

Cóż, większość rzeczy XML (lub opartych na adnotacjach) mówi Springowi takie rzeczy jak:

  • Gdy ktoś poprosi o „HammerStore”, chcę, abyś utworzył instancję example.HammerStorei zwrócił ją. Następnym razem buforuj instancję, ponieważ musi istnieć tylko jeden sklep.
  • Gdy ktoś prosi o „SomeHammer”, chcę, abyś poprosił o „HammerStore” i zwrócił wynik metody sklepu makeHammer(). Czy nie buforują ten wynik.
  • Gdy ktoś poprosi o „SomeWrench”, chcę, abyś utworzył instancję example.WrenchImpl, użyj ustawienia konfiguracji gaugeAmounti umieść ją we właściwości instancji setWrenchSize(). Nie buforuj wyniku.
  • Gdy ktoś poprosi o „numer lokalny”, chcę, abyś utworzył instancję example.PlumberImpl. Umieść ciąg „Pedro” w swojej setName()metodzie, umieść „SomeHammer” w swojej setHammer()metodzie i umieść „SomeWrench” w swojej setWrench()metodzie. Zwróć wynik i zapisz w pamięci podręcznej na później, ponieważ potrzebujemy tylko jednego hydraulika.

W ten sposób Spring pozwala łączyć komponenty, oznaczać je, kontrolować ich cykle życia / buforowanie oraz zmieniać zachowanie w zależności od konfiguracji.

Aby ułatwić [testowanie] zazwyczaj tworzę (przynajmniej) dwie wersje metody: jedną, która wykorzystuje zmienne instancji, i jedną, która wykorzystuje tylko zmienne przekazane do metody.

To brzmi jak duże obciążenie, które nie ma dla mnie dużej korzyści. Zamiast tego spraw , aby zmienne instancji miały protectedwidoczność lub widoczność pakietu , i zlokalizuj testy jednostkowe w tym samym com.mycompany.whateverpakiecie. W ten sposób możesz sprawdzać i zmieniać zmienne instancji w dowolnym momencie podczas testowania.

Darien
źródło
65

Po pierwsze, czym jest wstrzykiwanie zależności?

Prosty. Masz klasę, ma ona prywatne pole (ustawione na null) i deklarujesz publiczny setter, który podaje wartość dla tego pola. Innymi słowy, zależność klasy (pola) jest wstrzykiwana przez klasę zewnętrzną (przez seter). Otóż ​​to. Nic magicznego.

Po drugie, Spring może być używany bez XML (lub bardzo mało)

Jeśli zagłębisz się w Spring 3.0.5.GA lub nowszy, możesz skorzystać z obsługi wstrzykiwania zależności z JDK6 +. Oznacza to, że można połączyć zależności za pomocą adnotacji @Componenti @Resource.

Po co w ogóle używać Spring?

Oczywiście wstrzykiwanie zależności promuje bardzo łatwe testowanie jednostkowe, ponieważ wszystkie klasy mają ustawiacze ważnych zależności i można je łatwo wyśmiewać za pomocą ulubionej struktury próbnej, aby zapewnić wymagane zachowanie.

Poza tym Spring udostępnia również wiele szablonów, które działają jak klasy podstawowe, dzięki czemu korzystanie ze standardowych technologii JEE jest dziecinnie proste. Na przykład JdbcTemplate działa dobrze z JDBC, JpaTemplate robi dobre rzeczy z JPA, JmsTemplate sprawia, że ​​JMS jest bardzo prosty. RestTemplate jest po prostu niesamowity w swojej prostocie. Na przykład:

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

i jesteś skończony. Parametry są wstrzykiwane i wystarczy podać adnotacje JAXB dla MyJaxbObject. To nie powinno zająć w ogóle czasu, jeśli automatycznie wygenerowałeś je z XSD przy użyciu wtyczki Maven JAXB. Zwróć uwagę, że nie odbywał się tam casting ani nie było potrzeby ogłaszania marszałka. To wszystko jest zrobione dla ciebie.

Mógłbym bez końca opowiadać o cudach wiosny, ale być może najlepszą rzeczą do zrobienia jest wypróbowanie prostego skoku kodu, w którym próbujesz połączyć usługę internetową RESTful w celu wypompowania danych z wstrzykniętego DAO, który obsługuje transakcje.

Gary Rowe
źródło
4
tak RestTemplate jest niesamowity. Mam około 100 wierszy kodu, które mogę wyrzucić i zastąpić 2-3 wierszami.
Kevin
11
Aby nitpick: Dependency Injection obejmuje również podejście oparte na konstruktorze. Nie musisz koniecznie mieć seterów.
Darien
28

Po pierwsze, twoje rozumienie zastrzyku uzależnienia nie jest zasadniczo błędne, ale całkowicie różni się od tego, co większość ludzi ma na myśli, kiedy używa tego terminu. To, co opisujesz, jest dość dziwnym i niekonwencjonalnym sposobem na uzyskanie testowalności. Radzę odejść od tego, ponieważ inni programiści będą raczej zaskoczeni tego rodzaju kodem.

Wstrzykiwanie zależności, jak to jest ogólnie rozumiane (i implementowane przez Spring), oznacza, że ​​zależności, które ma klasa (np. Źródło danych JDBC), nie są pobierane przez samą klasę, ale „wstrzykiwane” przez kontener podczas tworzenia instancji. Nie masz więc dwóch wersji każdej metody korzystającej z źródła danych; zamiast tego masz jedną konfigurację wstrzykiwania zależności, w której wstrzykuje się „prawdziwe” źródło danych i drugą, w której wstrzykuje się próbkę. Lub, jeśli wstrzyknięcie odbywa się za pośrednictwem konstruktora lub modułu pobierającego, kod testowy może wykonać wstrzyknięcie jawnie.

Po drugie, Spring to nie tylko zastrzyk zależności, ale to jego podstawowa funkcjonalność. Zapewnia również deklaratywne transakcje, planowanie zadań, uwierzytelnianie i szereg innych funkcji (w tym pełnowartościowego środowiska internetowego MVC), które mogą być potrzebne. Istnieją inne frameworki, które zapewniają tę samą funkcjonalność, ale inne niż Spring, tylko Java EE ma je wszystkie zintegrowane.

Michael Borgwardt
źródło
OP doskonale rozumie DI
Basilevs
19

Dlaczego chcesz użyć Springa, możesz go przeczytać na stronie http://www.wrox.com/WileyCDA/Section/Why-Use-the-Spring-Framework-.id-130098.html

W podsumowaniu :

  • Aplikacje J2EE zwykle zawierają nadmierne ilości kodu „hydraulicznego”. Wiele recenzji kodu wielokrotnie ujawnia dużą część kodu, który nic nie robi: kod wyszukiwania JNDI, Transfer Objects, bloki try / catch, aby zdobyć i zwolnić zasoby JDBC. . . . Pisanie i utrzymywanie takiego kodu hydraulicznego stanowi znaczne obciążenie zasobów, które powinny być skoncentrowane na domenie biznesowej aplikacji.

  • Wiele aplikacji J2EE używa rozproszonego modelu obiektowego, gdy jest to nieodpowiednie. Jest to jedna z głównych przyczyn nadmiernego duplikowania kodu i kodu. W wielu przypadkach jest to również błędne koncepcyjnie; aplikacje dystrybuowane wewnętrznie są bardziej złożone niż aplikacje kolokowane i często znacznie mniej wydajne. Oczywiście, jeśli wymagania biznesowe narzucają architekturę rozproszoną, musisz wdrożyć architekturę rozproszoną i zaakceptować kompromis, który się z tym wiąże (a Spring oferuje funkcje pomocne w takich scenariuszach). Ale nie powinieneś tego robić bez ważnego powodu.

  • Model komponentu EJB jest nadmiernie złożony. EJB został pomyślany jako sposób na zmniejszenie złożoności podczas wdrażania logiki biznesowej w aplikacjach J2EE; w praktyce nie udało się osiągnąć tego celu.

  • EJB jest nadużywane. EJB został zasadniczo zaprojektowany do wewnętrznych aplikacji transakcyjnych. Chociaż prawie wszystkie nietrywialne aplikacje są transakcyjne, dystrybucji nie należy wbudowywać w podstawowy model komponentów.

  • Wiele „wzorców projektowych J2EE” nie jest w rzeczywistości wzorcami projektowymi, lecz obejściami ograniczeń technologicznych. Nadużywanie dystrybucji i stosowanie złożonych interfejsów API, takich jak EJB, wygenerowało wiele wątpliwych wzorców projektowych; ważne jest ich krytyczne zbadanie i poszukiwanie prostszych, bardziej produktywnych podejść.

  • Aplikacje J2EE są trudne do przetestowania jednostkowego. Interfejsy API J2EE, a zwłaszcza model komponentu EJB, zostały zdefiniowane przed uruchomieniem mechanizmu zwinnego. Dlatego ich konstrukcja nie uwzględnia łatwości testowania jednostkowego. Zarówno interfejsy API, jak i umowy niejawne zaskakująco trudno jest testować aplikacje oparte na EJB i wielu innych interfejsach API J2EE poza serwerem aplikacji. Jednak testy jednostkowe poza serwerem aplikacji są niezbędne, aby osiągnąć wysoki zasięg testów i odtworzyć wiele scenariuszy awarii, takich jak utrata łączności z bazą danych. Bardzo ważne jest również zapewnienie szybkiego uruchomienia testów podczas procesu programowania lub konserwacji, minimalizując nieproduktywny czas oczekiwania na ponowne wdrożenie.

  • Niektóre technologie J2EE po prostu zawiodły. Głównym przestępcą są tutaj fasole jednostek, które okazały się katastrofalne pod względem produktywności i ograniczeń związanych z orientacją obiektu.

Rudy
źródło
13

Kiedyś pisaliśmy proste, wydajne, szybkie aplikacje i usługi sieciowe przy użyciu tylko podstawowych Java, Servletów i JSP, HTML i XML, JDBC API. To było wystarczająco dobre; JUnit było dobrym narzędziem do testowania. Spoczywaliśmy spokojnie, że nasz kod działa.

Hibernacja pojawiła się, aby uprościć SQL i umożliwić prawdziwe mapowanie tabel bazy danych z obiektami Java, umożliwiając odzwierciedlenie relacji hierarchicznych w mapowaniu relacji obiektów lub ORM, jak to nazywamy. Kocham to. Zwłaszcza, że ​​nie musieliśmy mapować ResultSet z powrotem na obiekt Java lub typ danych.

Pojawiło się Struts, aby dodać wzór kontrolera widoku modelu do naszych aplikacji internetowych, było dobrze.

EJB były ogromnym kosztem, a ból i adnotacje sprawiały, że kod wyglądał jak zadrapanie kurczaka, a teraz Spring rzucił się na nas, niewinni ludzie. Wydaje mi się to po prostu przesadzeniem.

Na przykład teraz pakujemy nasz prosty adres URL jdbc, użytkownik, najpierw przechodzimy do pliku jdbc.properties, a następnie do właściwości hibernacji, a następnie do fasoli wiosennej po raz trzeci!

W porównaniu z tym wszystkim, rozważ uzyskanie połączenia tam, gdzie jest ono potrzebne, jest naprawdę tak proste, jak pokazano poniżej w czystej Javie, co naprawdę robimy po przejściu wszystkich tych gorących rzeczy z Springem:

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

To samo w sobie jest oczywiste, że jest to wielka runda i owijanie w kółko, aby zrobić prostą rzecz szybko i łatwo bez żadnych innych dużych korzyści. To jak zawijanie ton papieru prezentowego wokół drobnego miłego prezentu, który i tak jest wszystkim, co naprawdę masz.

Innym przykładem jest aktualizacja wsadowa. W Spring jest skomplikowany, obejmujący kilka klas interfejsów, zanim można użyć JdbcTemplate do aktualizacji wsadowej. W zwykłym jdbc jest to po prostu:

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

Nie może być prostsze ani szybsze.

Nie popieram tych ram. Przepraszam. Kto do cholery chce zastrzyków za każdym razem, gdy czegoś potrzebują?

Uma
źródło
6
ten kod jest prosty, ale gdzie jest zdefiniowana obsługa transkacji i jak ją testujesz? Obie rzeczy są uproszczone na wiosnę. Ponadto kod Java jest bezpośrednio powiązany z połączeniem db, chyba że przechowujesz adresy URL połączeń i hasła na zewnątrz, jest to również łatwiejsze do wiosny.
NimChimpsky
+1 dla tej odpowiedzi, aby odpowiedzieć na powyższy komentarz, mężczyzna używa własnych lekkich wzorców projektowych (GOF), singletonu do pulowania połączeń, klasy proxy, która dostarcza sql (ciąg) i wartości (tablica) do obiektu bazy danych (która metoda , zależy od metody http), dbobject obsługuje pule połączeń, transakcje itp., wykonując zapytanie, a następnie zwalniając. Zastosowanie jednego obiektu we wszystkich modułach, nikt nie potrzebuje nadmiernego kodu płyty kotła. punkt bonusowy z ustawieniem testów jednostkowych dla klasy proxy i dbobject.
user2727195,
Sprawdź jednak Spring-Data-JPA! Opisz adnotację pojęcia w jednostce, zaimplementuj interfejs i zdefiniuj podpisy metod przy użyciu rozsądnych nazw, takich jak findHammerByWeight (), a spring zaimplementuje metody dla Ciebie, zapewniając repozytorium do wstrzykiwania, którego możesz używać we wszystkich innych usługach biznesowych lub klasach kontrolerów .
mancini0
13

Co robi środowisko Spring?

Wiosna jest dziś nie tylko, tak zwana prostym ramem, jest kompletnym ekosystemem.

Tematy objęte ekosystemem wiosennym:

  • Spring Framework (np. Dependency Injection, AOP ...)

  • Wiosenna chmura

  • Dane wiosenne

  • Wiosenne bezpieczeństwo

  • Partia wiosenna

  • Spring Social

Zobacz tutaj pełne pokrycie ekosystemu. Możliwe jest wybieranie projektów, abyś mógł używać Google Guice dla DI i np. Spring Security do obsługi rzeczy związanych z bezpieczeństwem. Nie musisz kupować całego ekosystemu.

Sama struktura wiosenna obejmuje dziś głównie

  • Wstrzykiwanie zależności

  • Programowanie zorientowane na aspekty, w tym deklaratywne zarządzanie transakcjami Spring

  • Wiosenna aplikacja internetowa MVC i platforma usług internetowych RESTful

  • Podstawowa obsługa JDBC, JPA, JMS

Źródło spring.io

Ogólnie można powiedzieć, że Spring jest zbiorem zaimplementowanych wzorców i praktyk w kodzie, które mogą pomóc w ulepszeniu lub przyspieszeniu cyklu tworzenia aplikacji.

To, z czego jest najbardziej znana (podstawowa struktura), to możliwości w zakresie wstrzykiwania zależności . Sama sprężyna ma tak zwaną inwersję kontenera kontrolnego lub krótkiego kontenera IoC, a nawet krótszego kontenera (dla którego czasami „sprężyna” jest synonimem).

Co to jest wstrzyknięcie zależności?

Wstrzykiwanie zależności oznacza, że ​​Twój obiekt odbiera każdą zależność od innych obiektów za pośrednictwem mechanizmu zewnętrznego.

Załóżmy, że masz samochód. Typowym sposobem jego realizacji jest:

public class Car {

    Engine e;

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

}

Obiekt samochodu zależy od silnika. Ponieważ silnik jest zaimplementowany jako element samochodu, nie można go wymienić np. Na silnik testowy.

Teraz pojawia się zastrzyk zależności :

public class Car {

    Engine e;

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

}

Następnie możesz przełączać silniki. To, co widzisz powyżej, nazywa się iniekcją konstruktora . Istnieją inne rodzaje, takie jak np seter -injection lub metoda -injection. W jaki sposób Spring Ci w tym pomaga? Sprężyna pozwala oznaczać komponenty do wstrzyknięcia za pomocą adnotacji @Autowiredi automatycznie wykonuje okablowanie wstrzykiwanego obiektu - prawdopodobne jest, że komponent, który chcesz wstrzyknąć, sam ma zależności. Zastrzyki - że tak powiem - są oznaczone za pomocą@Component

public class Car {

    Engine e;

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

}

Ale to tylko jedna z wielu funkcji, które ma do zaoferowania wiosna.

Czy powinienem używać wiosny? Dlaczego lub dlaczego nie?

Ponieważ wiosna nie jest bardzo uciążliwa i oferuje wiele pomocy, które powinieneś rozważyć przy użyciu wiosny. Szczególnie w przypadku nowych projektów Spring Boot jest bardzo atrakcyjny. start.spring.io oferuje łatwy w użyciu interfejs point'n'click do wygenerowania szablonu projektu na początek. Można nawet użyć curldo pobrania szablonu:

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  |
+-----------------+-----------------------------------------+

...

Z drugiej strony frameworki takie jak Spark lub Dropwizard stanowią dobry punkt wyjścia do szybkiego tworzenia aplikacji internetowych.

Thomas Junk
źródło
1
Bardzo pouczająca odpowiedź!
GOXR3PLUS,
Uzgodniona, bardzo dobra odpowiedź. OP, sympatyzuję z tobą. Kilka osób pokazało mi też wiosenne dema, w których „upraszczają” kod, dodając plik XML i 2 warstwy pośrednie, aby mogli wywołać konstruktora na zajęciach :) Naprawdę musisz po prostu zanurkować lub przejść do naprawdę dobra prezentacja i ostatecznie stanie się jasne, jakie są zalety i wady
Adam Hughes
4

Jest to framework napisany w Javie, zawierający wiele rzeczy, dzięki którym twoja aplikacja internetowa jest funkcjonalna (np. Obsługa internacjonalizacji). To także dobry sposób na uporządkowanie aplikacji w warstwy. Użyj go, pozwoli to zaoszczędzić dużo czasu na dłuższą metę.

Dobra książka do nauki o Spring to: Expert Spring MVC i Web Flow

Bernard
źródło