Cześć! Postanowiłem sobie, że wrócę do nagrywania filmów na YouTube. Mam nadzieję, że tym razem seria tworzonych materiałów będzie dłuższa niż ostatnio… Przy tej okazji zdecydowałem, że materiały publikowane na tej platformie będę przerabiał tak, aby zamieszczać je jako publikacje na bloga. Taka decyzja była podyktowana tym, że część ludzi lubi oglądać materiały dostępne w Internecie, a część czytać. Na start weźmiemy na tapet tematy lżejsze. Dla części będzie to pewnie coś nowego, dla innych powtórka znanych im pojęć. Jednak z czasem wejdziemy w coraz to bardziej zaawansowane zagadnienia. Także nie przedłużając, zapraszam do lektury!
Jedna z zalet Springa
Dziś wejdziemy w świat Spring’a, a dokładniej w jedno z pojęć stojących za jego powstaniem. Spring to framework, który zrewolucjonizował sposób, w jaki aktualnie tworzymy aplikacje oparte o Javę, ale i nie tylko. Jego kluczową zaletą jest to, że zwalnia nas z myślenia o zarządzaniu zależnościami w naszych aplikacjach, pozwalając nam skupić się na logice biznesowej, zamiast na klejeniu wszystkich komponentów.
Aby poczuć tą korzyści Spring’a, zaczniemy od stworzenia prostej aplikacji opartej na Spring Boot. W uproszczeniu Spring Boot jest Spring’iem na sterydach, który konfiguruje środowisko aplikacyjne (integrację z narzędziami) za nas. Projekt, na potrzeby dzisiejszej prezentacji, utworzymy wykorzystując narzędzie o nazwie Spring Initializr (dostępnym na stronie Spring’a lub w IDE, jakim jest IntelliJ). W ten sposób możemy łatwo wygenerować szkielet aplikacji, co jest świetnym punktem wyjścia do nauki i eksperymentów.
Podejście manualne vs Spring
Na potrzeby naszego demo stworzymy trzy klasy serwisów: ServiceA
, ServiceB
, i ServiceC
. Pierwsze dwie klasy będą wydmuszkami. Natomiast serwis ServiceC
będzie od nich zależał. Zależność jest stricte akademicka. Serwis ServiceC
nie będzie z nich korzystał, aby wykonać swoje zadanie. Jest to prosta metoda wyświetlającą zdanie na konsolę.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class ServiceA {
}
public class ServiceB {
}
public class ServiceC {
private final ServiceA serviceA;
private final ServiceB serviceB;
public ServiceC(ServiceA serviceA, ServiceB serviceB) {
this.serviceA = serviceA;
this.serviceB = serviceB;
}
public void print() {
System.out.println("Hello from ServiceC");
}
}
Teraz skupimy się na manualnym połączeniu tych klas w aplikacji uruchamianej bez Spring’a. Zobaczymy, ile wymaga to od nas pracy.
1
2
3
4
5
6
7
8
9
10
11
public class AppWithoutSpring {
public static void main(String[] args) {
ServiceA sa = new ServiceA();
ServiceB sb = new ServiceB();
ServiceC serviceC = new ServiceC(sa, sb);
serviceC.print();
}
}
Ręczne tworzenie instancji i łączenie zależności może być żmudne.
Magia Spring: Komponenty i Dependency Injection
Kiedy już mamy obraz tego, jak wygląda praca bez Spring’a, dodajemy coś, co czyni nasz kod magicznym – adnotacje @Component
i @Autowired
(o tej adnotacji pogadamy sobie jeszcze następnym razem). Spring automatycznie zajmuje się wstrzykiwaniem zależności, co znacząco upraszcza naszą pracę i pozwala skupić się na celach aplikacji, zamiast na jej strukturze.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@Component
public class ServiceA {
}
@Component
public class ServiceB {
}
@Component
public class ServiceC {
private final ServiceA serviceA;
private final ServiceB serviceB;
public ServiceC(ServiceA serviceA, ServiceB serviceB) {
this.serviceA = serviceA;
this.serviceB = serviceB;
}
public void print() {
System.out.println("Hello from ServiceC");
}
}
Przy okazji demo skorzystamy z interfejsu CommandLineRunner
. Jego zaletą jest to, że pozwala on nam uruchamiać dodatkowe funkcje po starcie aplikacji. Jednak uwaga, dana klasa go implementująca musi być komponentem Springa. W naszym przypadku skorzystamy z niego tylko, dlatego że pole o typie ServiceC
nie może być wykorzystane w statycznej metodzie startowej. Stąd taka mała sztuczka.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@SpringBootApplication
public class AppWithSpring implements CommandLineRunner {
@Autowired
ServiceC serviceC;
public static void main(String[] args) {
SpringApplication.run(AppWithSpring.class, args);
}
@Override
public void run(String... args) throws Exception {
serviceC.print();
}
}
Co dalej?
W przyszłych wpisach zanurzymy się głębiej w tematykę takich adnotacji jak @Autowired
, porozmawiamy o najlepszych praktykach projektowych z użyciem Spring’a oraz zbadamy alternatywne podejścia do tworzenia komponentów w naszej aplikacji. Spring oferuje wiele zaawansowanych rozwiązań, które warto poznać.