Stało się. Po ośmiu odcinkach dotykających jedynie spraw „około-programowych” w końcu przechodzimy do pisania kodu per se. W niniejszym artykule poznamy czym tak właściwie jest Spring framework i jaki ma wpływ na pracę Java developera.
Uwaga! W tej serii zajmuję się opisowym przedstawieniem tematu, a celem jest zapoznanie z zagadnieniem w sposób luźny i zrozumiały dla nowicjusza. W związku z tym wiele elementów siłą rzeczy musi zostać pominiętych. Tych z was, którzy chcieliby się dowiedzieć więcej, zapraszam do źródeł na końcu artykułu.
Już na początku mojej przygody z Javą wiedziałem, że istnieje coś takiego jak Spring, że jest to jakiś framework do tego języka, że jest szalenie popularny i że nikt nie pisze już kodu biznesowego w czystej Javie, tylko właśnie za pomocą Springa (albo Javy EE, o czym za chwilę).
Przyznam szczerze, że pomysł na cały ten cykl narodził się właśnie od Springa. Chciałem opisać jego istotę, zasady, zastosowanie – ale kiedy głowiłem się jak to wszystko zmieścić w jednym wpisie, doszedłem do wniosku, że nowicjusz, który jeszcze nie odróżnia listy od setu, tego nie przełknie bo zabraknie mu innych podstaw, dotyczących np. REST-a czy SQL-a. Tym trzeba się było zająć w pierwszej kolejności.
Ale czym tak właściwie jest Spring?
Problem ze Springiem jest taki, że o ile bardzo zajebiście ułatwia tworzenie aplikacji, to już zrozumienie magii, która za nim stoi do najłatwiejszych nie należy.
Dlatego do dzisiejszego zagadnienia trzeba przystępować powoli, solidnym kijem sprawdzając każdy kolejny stopień zanim zdecydujemy się postawić na nim stopę.
W życiu początkującego programisty przychodzi ten moment kiedy pojedyncza klasa zaczyna go ograniczać i nie pozwala mu rozwinąć skrzydeł. Tworzy więcej klas. Wychodzi poza ramy jednego pakietu i buduje coraz większe struktury. Implementuje swój pierwszy interfejs i …

Po dopisaniu kawałka w stylu:
public class Example implements MyInterface
IntelliJ zaczyna się świecić, gdyż zauważył błąd: trzeba zaimplementować metody interfejsu, który właśnie dodaliśmy do klasy.

Klikamy sugerowaną opcję w menu kontekstowym i natychmiast pojawia się metoda z wybranego interfejsu, gotowa do zaimplementowania i ochrzczona żółtym napisem
@Override
Tak zazwyczaj wygląda nasz pierwszy kontakt z adnotacjami. Ale czym dokładnie jest taka adnotacja?
Jeśli chodzi o rzeczone @Override to jest to nic innego jak informacja żeby dev pamiętał, że metoda pochodzi z interfejsu (albo z klasy dziedziczonej) i nie może sobie ot tak zmieniać jej sygnatury – trzeba trzymać się z góry ustalonego kontraktu. Java informuje nas o tym adnotacją, choć efekt byłby zupełnie taki sam jakbyśmy dali tam po prostu zwykły komentarz.

Ale to nie wszystko, bo choć adnotacje mogą spełniać jedynie funkcje informacyjne, to równie dobrze możemy z nich wycisnąć znacznie więcej.
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyAnnotation {}
Każda adnotacja zaczyna się od (nomen omen) adnotacji:
@Retention
Mówi ona kompilatorowi kiedy ma być „widoczna”:
- @Retention(RetentionPolicy.RUNTIME) – widać ją w czasie działania programu
- @Retention(RetentionPolicy.SOURCE) – widać ją tylko w kodzie źródłowym
- @Retention(RetentionPolicy.CLASS) – widzi ją kompilator ale jest bezużyteczna w czasie działania aplikacji
@Override ma tu ustawione SOURCE, bo więcej mu nie potrzeba. Zabawa zaczyna się dopiero jak zrobimy tam RUNTIME.
Taka adnotacja jest znacznikiem, która może targetować daną klasę, jej obiekty i metody. Możemy sprawić, że każda stworzona instancja zaznaczonej klasy będzie lądować na osobnej liście, że jej funkcje będą wywoływane bez naszego udziału.
– Ok, fajnie. Tylko co to ma wspólnego ze Springiem?
– …

Spring framework to system adnotacji, który za pomocą tzw. Reflection API ma dostęp do klas i metod które tworzymy.
Refleksja (Reflection API) to odwoływanie się nie do metod i obiektów jak to robimy normalnie, tylko do samej klasy/metody i jej pól. Możemy np. sprawdzić, czy klasa ma jakąś adnotację, albo przypisać dowolną wartość dowolnemu atrybutowi – nawet prywatnemu.
Brzmi to jak coś skomplikowanego, ale wystarczy sobie uzmysłowić, że Spring to nie jest coś z czego Ty korzystasz:
Spring to coś co korzysta z Ciebie.
A dokładniej: z klas, obiektów, atrybutów i metod które ty stworzysz. W pracy z czystą Javą piszesz nowe klasy kiedy ich potrzebujesz, implementujesz metody, które są ci w danej chwili potrzebne. Gdy dodasz do tego Springa to zupełnie jakbyś dostał kolegę do wspólnego pisania kodu: ty dodajesz nowe klasy, ale to on ich używa i tworzy ich obiekty.
Technicznie rzecz biorąc taka kooperacja nosi nazwę:
Dependency Inversion
Zasada odwrócenia zależności – ostatnia literka w skrócie SOLID

(ang. „Don’t call us, we’ll call you.” ma więcej sensu, bo po angielsku „wołamy metodę” – „call a method”)
To właśnie jest to największe zaskoczenie przy pierwszym podejściu do Springa. Oglądając tutorial jak koduje profesjonalista widziałem, że tworzy klasy, ale nigdzie nie tworzy ich obiektów. Ustawia gettery i settery ale nigdzie się do nich nie odnosi. W jednej klasie dodaje metodę zwracającą obiekt drugiej klasy, a w trzeciej korzysta z tego obiektu jakby już był zbudowany, chociaż to nigdzie nie miało miejsca!
Zagadka goni zagadkę!
Przejście z czystej Javy na Springa może okazać się szokiem, to trochę jakbyśmy zaczęli się uczyć innego języka programowania. Ale tylko na początku. Trzeba po prostu zmienić podejście na:
Spring to worek z obiektami
Oprócz tego, że omawiany framework jest systemem adnotacji, to jest to również coś na podobieństwo HashMapy – kluczem jest tutaj klasa którą oddaliśmy Springowi do zarządzania, a wartością – jej obiekt (liczba pojedyncza, Spring operuje na Singletonach).
Spring context, bo o nim mowa, to taki mechanizm, który przy starcie naszej aplikacji najpierw przechadza się po wszystkich pakietach, sprawdza klasy i jeśli mają odpowiednie adnotacje, np.
- @Configuration
- @Component
- @Controller
- @Service
to tworzy ich obiekt i dodaje do swojego worka kontekstu. Kiedy jedna klasa zarządzana* przez Springa będzie potrzebować obiektu innej klasy zarządzanej* przez Springa to skorzysta właśnie z tego znajdującego się w kontekście.
Nie ma potrzeby używać konstruktora,
Spring zrobi to za nas.
(*) Należy pamiętać, że obok klas „springowych”- z jego adnotacjami, możemy mieć też te zwykłe, o których Spring nic nie wie. Ale wtedy nie możemy ich ze sobą mieszać – jeśli „czysta” klasa potrzebuje obiektu klasy „springowej” to nie może skorzystać z tego w kontekście, tylko trzeba go urodzić siłami natury, że tak to ujmę. I na odwrót.

O Javie EE będzie krótko,
bo na więcej nie zasługuje.
Nie zrozumcie mnie źle – Java Enterprise Edition bardzo pomagała programistom pisać aplikacje „od zera aż do w pełni działającego API umieszczonego na serwerze”. Kluczem jest tu jednak czas przeszły w słowie „pomagała”.
Lepsze jest wrogiem dobrego.
Java EE w porównaniu do Springa jest o wiele trudniejsza do nauczenia i to właśnie ten fakt przyczynił się do jej upadku… który trwa do dzisiaj. Owszem, wciąż pojawiają się oferty pracy z tą technologią, ale są one skierowane głównie do seniorów, którzy już się jej nauczyli. Nie jestem w stanie wyobrazić sobie nowego projektu którego twórcy świadomie i na trzeźwo decydują się na wybór Javy w wersji Enterprise zamiast Springa.
Jeśli traficie na ogłoszenie w którym szukają programisty znającego JEE to na 99,(9)% będzie to oznaczało zanurzenie się w bagnie legacy code z którym nikt przy zdrowych zmysłach nie chce mieć nic wspólnego.
Podsumowując:
Spring i Java EE służą do tego samego,
ale Spring robi to lepiej.
Koniec części pierwszej
Postanowiłem podzielić artykuł o Springu na dwa kawałki. Ten, który teraz czytacie pokrywa teorię: tłumaczy czym jest Spring, jak działa i do czego służy. Natomiast w następnym odcinku skupimy się już na elementach tego frameworka: jakie są dostępne oraz jak ich używać w praktyce. Wytłumaczę również (a raczej „przede wszystkim”) czym jest
Spring Boot
Ten „framework do frameworka” dorzuca brakującą wisienkę na torcie do Springa w taki sposób, że większość programistów Javy już dawno przestała tworzyć nowe projekty w „czystym Springu”. O tym co dokładnie (i w jaki sposób to) robi, dowiecie się już niebawem.
Źródła:
Przemek Bykowski: Adnotacje blog/POL
Przemek Bykowski: Wprowadzenie do Springa YT/POL
Kurs mikroserwisów i Springa na Udemy (płatne) POL