IT355 - WEB SISTEMI 2
Uvod u Spring
Lekcija 01
IT355 - WEB SISTEMI 2
Lekcija 01
UVOD U SPRING
Uvod u Spring
Poglavlje 1: Šta je Spring i zašto koristimo aplikacione okvire
Poglavlje 2: Spring ekosistem
Poglavlje 3: Spring u scenarijima iz stvarnog sveta
Poglavlje 4: Spring kontekst
Poglavlje 5: Dodavanje novih bean-ova u Spring kontekst
Poglavlje 6: Pokazna vežba
Poglavlje 7: Individualna vežba 1
Zaključak
Copyright © 2017 – UNIVERZITET METROPOLITAN, Beograd. Sva prava zadržana. Bez prethodne pismene dozvole
od strane Univerziteta METROPOLITAN zabranjena je reprodukcija, transfer, distribucija ili memorisanje nekog
dela ili čitavih sadržaja ovog dokumenta., kopiranjem, snimanjem, elektronskim putem, skeniranjem ili na bilo
koji drugi način.
Copyright © 2017 BELGRADE METROPOLITAN UNIVERSITY. All rights reserved. No part of this publication may
be reproduced, stored in a retrieval system or transmitted in any form or by any means, electronic, mechanical,
photocopying, recording, scanning or otherwise, without the prior written permission of Belgrade Metropolitan
University.
www.metropolitan.ac.rs
Uvod
UVOD
Spring je Java platforma koja obezbeđuje obimnu infrastrukturnu
podršku za razvoj Java aplikacija.
Spring okvir (Spring Framework) predstavlja Java platformu koja obezbeđuje obimnu
infrastrukturnu podršku za razvoj širokog spektra Java aplikacija. Celokupnom infrastrukturom
upravlja Spring pa tim za razvoj može da se fokusira isključivo na razvoj konkretnih programa.
Spring omogućava kreiranje aplikacija iz POJO (plain old Java objects) objekata i primenu
složenih (enterprise) servisa na POJO objekte. Navedene funkcionalnosti Spring okvira
primenjuju se u potpunosti na Java SE (Java Standard Edition) model programiranja i u
potpunosti, ili parcijalno, na Java EE (Java Enterprise Edition) model programiranja.
Programer može da ima brojne benefite kada koristi Spring okvir za kreiranje svojih Java
programa. Slede neke očigledne prednosti koje programer može da ima upotrebom ove
platforme:
• Izvršavanje Java metoda kroz transakciju sa bazom podataka bez potrebe za rukovanjem
konkretnim API - jem za transakcije;
• Kreiranje HTTP krajnje tačke (HTTP endpoint) lokalne Java metode bez potrebe za
rukovanjem konkretnim Servlet API;
• Kreiranje rukovalaca poruka (message handler ) lokalne Java metode bez potrebe za
rukovanjem konkretnim JMS API;
• Kreiranje upravljačkih operacija (management operation) lokalne Java metode bez
potrebe za rukovanjem konkretnim JMX API.
Tokom ovog predmeta studenti će steći široku sliku o savremenoj primeni Spring okvira za
razvoj Java veb aplikacija. Materijali će se oslanjati na pažljivo birane primere koji će pratiti
svako izlaganje koje se odnosi na koncepte i principe Spring okvira.
3
Poglavlje 1
Šta je Spring i zašto koristimo
aplikacione okvire
SPRING FRAMEWORK
Spring framework je aplikacioni okvir koji je deo Java ekosistema.
Spring framework (skraćeno, Spring ) je aplikacioni okvir koji je deo Java ekosistema.
Aplikacioni okvir je skup uobičajenih softverskih funkcionalnosti koje pružaju osnovnu
strukturu za razvoj aplikacija.
Aplikacioni okvir olakšava proces pisanja aplikacije tako što uklanja potrebu za pisanjem
celokupnog programskog koda od nule. Danas koristimo Spring za razvoj različitih vrsta
aplikacija, od velikih backendrešenja do aplikacija za automatizovano testiranje. Spring je
veoma popularan, a programeri su ga počeli sve češće koristiti i sa drugim JVM jezicima osim
Jave. Poslednjih godina značajan rast je primetan kod broja programera koji koriste Spring sa
Kotlinom za razvoj moblinih aplikacija.
Pitanja koja postavljamo su: Šta je aplikacioni okvir (engl. framework)? Kako se
ovaj koncept pojavio i zašto?
Da biste bili motivisani da koristite nešto, morate znati kako vam to donosi vrednost. To
važi i za Spring. Aplikacioni okvir je skup funkcionalnosti na osnovu kojih gradimo aplikacije.
Aplikacioni okvir nam pruža širok spektar alata i funkcionalnosti koje možemo koristiti za
izgradnju aplikacija. Ne morate koristiti sve funkcije koje okvir nudi. U zavisnosti od zahteva
aplikacije koju pravite, izabraćete odgovarajuće delove okvira koje ćete koristiti.
Sledeća analogija kada govorimo o aplikacionim okvirima može biti od koristi za razumevanje:
Da li ste ikada kupili komad nameštaja iz „uradi sam“ prodavnice poput Ikee? Recimo da
kupite garderober – nećete dobiti sklopljen garderober, već odgovarajuće komponente koje su
vam potrebne da ga sastavite i priručnik sa uputstvima kako da ga sastavite. Sada zamislite
da ste naručili garderober, ali umesto da dobijete samo odgovarajuće delove, dobijete sve
moguće komponente koje možete koristiti da sastavite bilo koji komad nameštaja: sto,
garderober itd. Ako želite garderober, morate pronaći prave delove i sastaviti ih. To je kao
aplikacioni okvir.
Aplikacioni okvir vam nudi različite softverske komponente koje su vam potrebne za izradu
aplikacije. Morate znati koje funkcije da odaberete i kako da ih sastavite kako biste postigli
željeni rezultat.
4
Poglavlje 1 Šta je Spring i zašto koristimo aplikacione okvire
ZAŠTO TREBA DA KORISTIMO OKVIRE?
Aplikacioni okvir je skup funkcionalnosti na osnovu kojih gradimo
aplikacije.
Ideja okvira nije nova. Kroz istoriju razvoja softvera, programeri su primetili da mogu ponovo
koristiti delove koda koje su napisali u više aplikacija. U početku, kada nije bilo mnogo
aplikacija, svaka aplikacija bila je jedinstvena i razvijala se od nule koristeći određeni
programski jezik. Kada se oblast razvoja softvera proširila i kada je na tržištu počelo da se
pojavljuje sve više aplikacija, postalo je lakše uočiti da mnoge od njih imaju slične zahteve:
• Beleženje grešaka, upozorenja i informativnih poruka pojavljuje se u svakoj aplikaciji.
• Većina aplikacija koristi transakcije za obradu promena podataka. Transakcije
predstavljaju važan mehanizam koji brine o konzistentnosti podataka. O ovoj temi ćemo
detaljnije govoriti u nekoj od narednih lekcija
• Većina aplikacija koristi zaštitne mehanizme protiv istih uobičajenih ranjivosti.
• Većina aplikacija koristi slične načine komunikacije međusobno.
• Većina aplikacija koristi slične mehanizme za poboljšanje performansi, kao što su
keširanje ili kompresija podataka.
I lista se nastavlja. Ispostavlja se da je kod poslovne logike koji se implementira u aplikaciji
znatno manji od osnove koja je zajednička za sve aplikacije. Kod poslovne logike je kod
koji implementira poslovne zahteve aplikacije. Ovaj kod implementira očekivanja korisnika u
aplikaciji. Na primer, „klikom na određeni link generisaće se faktura“ je nešto što korisnici
očekuju da se dogodi.
Deo koda aplikacije koju razvijate implementira ovu funkcionalnost, i taj deo koda programeri
nazivaju kodom poslovne logike. Međutim, svaka aplikacija mora voditi računa i o nekoliko
drugih aspekata: sigurnosti, beleženju događaja, konzistentnosti podataka itd. (vidi sliku
1.1). Slika 1.1 definiše da je korisnička perspektiva poput ledenog brega. Korisnici uglavnom
primećuju rezultate koda poslovne logike, ali to je samo mali deo koji gradi potpunu
funkcionalnost aplikacije. Kao što je većina ledenog brega ispod površine vode, tako i u
aplikaciji ne vidimo većinu koda, jer ga obezbeđuju zavisnosti.
Slika 1.1 Skriveni slojevi aplikacije Izvor: autor
5
Poglavlje 1 Šta je Spring i zašto koristimo aplikacione okvire
Poslovna logika razlikuje aplikacije po funkcionalnosti, dok tehničke komponente poput
čuvanja podataka, sigurnosti i keširanja mogu biti iste. Njihovo ponovno korišćenje štedi
vreme, smanjuje greške i olakšava podršku zajednice.
6
Poglavlje 2
Spring ekosistem
SPRING KAO EKOSISTEM OKVIRA
Obično se Spring naziva okvirom, ali je on mnogo složeniji. Spring je
ekosistem okvira.
U stvarnim situacijama, uobičajeno je koristiti različite okvire zajedno, gde je svaki okvir
dizajniran da vam pomogne da implementirate određeni deo aplikacije brže. Obično se Spring
naziva okvirom, ali je on mnogo složeniji. Spring je ekosistem okvira. Obično, kada programeri
govore o Spring okviru, misle na deo softverskih kapaciteta koji uključuje sledeće:
• Spring Core —Jedan od fundamentalnih delova Spring-a koji uključuje osnovne
mogućnosti. Jedna od tih karakteristika je Spring kontekst . Spring kontekst je temelj
Spring okvira koji omogućava Spring-u da upravlja instancama vaše aplikacije. Takođe,
kao deo Spring Core-a, nalazite funkcionalnost Spring aspekata . Aspekti pomažu Springu da presreće i manipuliše metodama koje definišete u svojoj aplikaciji. Spring Expression
Language (SpEL ) je još jedna mogućnost koju ćete pronaći kao deo Spring Core-a, koja
vam omogućava da opisujete konfiguracije za Spring koristeći određeni jezik. Sve ove
nove pojmove ćemo obraditi detaljnije tokom predmeta. Uskoro ćete shvatiti da Spring
Core sadrži mehanizme koje Spring koristi za integraciju u vašu aplikaciju.
• Spring model-view-controller(MVC )—Deo Spring okvira koji vam omogućava da razvijate
web aplikacije koje koriste HTTP zahteve.
• Spring pristup podacima (engl. Spring Data Access) —Takođe jedan od fundamentalnih
delova Spring-a. Pruža osnovne alate koje možete koristiti za povezivanje sa bazama
podataka kako biste implementirali sloj trajne memorije vaše aplikacije.
• Spring testiranje—Deo koji sadrži alate koji su vam potrebni da pišete testove za vašu
Spring aplikaciju.
U početku možete zamisliti Spring okvir kao solarni sistem, gde Spring Core predstavlja
zvezdu u sredini koja drži ceo okvir zajedno (slika 2.1).
7
Poglavlje 2 Spring ekosistem
Slika 2.1 Ilustracija Spring ekosistema Izvor: [1]
SPRING CORE: OSNOVA SPRING RADNOG OKVIRA
Spring Core je deo Spring okvira koji obezbeđuje osnovne mehanizme
za integraciju u aplikacije.
Spring Core je deo Spring okvira koji obezbeđuje osnovne mehanizme za integraciju u
aplikacije. Spring funkcioniše na principu inverzije kontrole ( IoC - Inversion of Control).
Kada koristimo ovaj princip, umesto da aplikacija sama kontroliše izvršavanje, kontrolu
prepuštamo nekom drugom softverskom sloju—u ovom slučaju, Spring okviru. Putem
konfiguracija, upućujemo okvir kako da upravlja kodom koji pišemo, a koji definiše logiku
aplikacije. Ovde se nalazi „inverzija“ u IoC konceptu: ne dozvoljavamo aplikaciji da sama
kontroliše izvršavanje pomoću sopstvenog koda i zavisnosti. Umesto toga, omogućavamo
okviru (zavisnosti) da upravlja aplikacijom i njenim kodom (slika 2.2). Umesto da izvršava svoj
vlastiti kod, koji koristi nekoliko drugih zavisnosti, u slučaju IoC scenarija, izvršenje aplikacije
kontroliše zavisnost.
Spring okvir kontroliše aplikaciju tokom njenog izvršenja. Stoga implementira IoC scenarije
izvršenja.
Jednostavno rečeno, Inversion of Control (IoC) je princip u kojem ne pišeš sam kako će neki
objekat biti napravljen ili povezan, već to prepuštaš drugom delu sistema. Na primer: umesto
da tvoja klasa sama pravi druge objekte koje koristi, neko drugi joj ih "ubrizga" – to može
biti frameworkili neka konfiguracija. Tako tvoj kod postaje jednostavniji, fleksibilniji i lakši za
testiranje. Zamisli kao da ideš u restoran – umesto da sam kuvaš (pravljenje objekta), ti
poručiš jelo, a kuhinja ( framework) ti ga donese.
8
Poglavlje 2 Spring ekosistem
Slika 2.2 Inverzija kontrole Izvor: autor
IoC kontejner povezuje Spring komponente i komponente vaše aplikacije sa okvirom.
Korišćenjem IoC kontejnera, koji se često naziva Spring kontekst, omogućavate Spring-u da
upravlja određenim objektima na način koji ste konfigurisali. Kroz lekcije učićemo i Spring
aspektno orijentisano programiranje (AOP). Spring može kontrolisati instance koje su dodate
u njegov IoC kontejner, a jedna od glavnih funkcionalnosti je presretanje metoda koje
predstavljaju ponašanje tih instanci. Ova mogućnost se naziva aspektovanje metoda. Spring
AOP je jedan od najčešćih načina na koji okvir komunicira sa onim što vaša aplikacija radi, što
ga čini ključnim delom Spring-a. Spring Core takođe obuhvata upravljanje resursima,
internacionalizaciju (i18n), konverziju tipova i Spring Expression Language (SpEL). Ove
karakteristike ćemo susretati kroz različite primere lekcijama.
SPRING DATA ACCESS, SPRING MVC I SPRING
TESTIRANJE
Spring Data Access olakšava rad sa bazama, Spring MVC omogućava
izgradnju web aplikacija, a Spring testiranje pruža podršku za lako i
efikasno testiranje aplikacija.
Za većinu aplikacija, ključno je da sačuvaju deo podataka koje obrađuju. Rad sa bazama
podataka je osnovni koncept, a u Spring-u se za upravljanje perzistencijom koristi Data Access
modul. Spring Data Access omogućava:
• Korišćenje JDBC-a,
• Integraciju sa ORM (objektno-relacionim mapiranjem) poput Hibernate-a
• Upravljanje transakcijama.
Najčešće aplikacije razvijene u Spring-u su web aplikacije, a u okviru Spring ekosistema
postoji veliki broj alata koji omogućavaju razvoj web aplikacija i servisa na različite načine.
Možete koristiti Spring MVC za razvoj aplikacija u tradicionalnom servlet stilu, što je danas
vrlo često u industriji.
Spring testing modul nudi bogat set alata za pisanje jediničnih i integracionih testova.
9
Poglavlje 2 Spring ekosistem
PROJEKTI IZ SPRING EKOSISTEMA
Spring ekosistem obuhvata veliku kolekciju drugih okvira koji se
međusobno integrišu i obezbeđuju širok spektar mogućnosti.
Spring ekosistem je mnogo više od mogućnosti koje smo do sada pomenuli. On obuhvata
veliku kolekciju drugih okvira koji se međusobno integrišu i i obezbeđuju širok spektar
mogućnosti.. Među njima se nalaze projekti kao što su:
Spring Data, Spring Security, Spring Cloud, Spring Batch, Spring Boot,
i mnogi drugi.
Kada razvijate aplikaciju, možete koristiti više ovih projekata zajedno. Na primer, možete
kreirati aplikaciju koristeći Spring Boot, Spring Security i Spring Data. U početnim lekcijama
ćemo raditi na manjim projektima koji koriste različite komponente Spring ekosistema. Kada
kažemo projekat, mislim na deo Spring ekosistema koji se razvija nezavisno. Svaki od ovih
projekata ima zaseban tim koji radi na njegovom unapređenju. Takođe, svaki projekat ima
zasebnu dokumentaciju i referencu na zvaničnoj Spring veb stranici: https://spring.io/projects.
Posebno ćemo se baviti Spring Data i Spring Boot projektima, jer se ovi projekti često
koriste u aplikacijama, pa ih je važno upoznati od samog početka. Spring Data je deo
Spring ekosistema koji omogućava lakšu integraciju sa bazama podataka i upravljanje slojem
perzistencije uz minimalan broj linija koda. Spring Data podržava rad sa SQL i NoSQL
tehnologijama, pružajući visoki nivo apstrakcije i pojednostavljujući rad sa bazama podataka.
NAPOMENA: Postoji razlika između Spring Data Access i Spring Data.
•Spring Data Access je modul Spring Core-a koji sadrži osnovne implementacije pristupa
podacima, poput mehanizama transakcija i alata za rad sa JDBC-om.
•Spring Data je nezavisni projekat koji dodatno poboljšava pristup bazama podataka i
pruža širi skup alata, omogućavajući povezivanje aplikacija sa različitim vrstama izvora
podataka.
Spring Boot je projekat iz Spring ekosistema koji uvodi koncept "konvencija umesto
konfiguracije" (convention over configuration). Glavna ideja ovog koncepta je da, umesto da
ručno podešavate sve konfiguracije okvira, Spring Boot nudi podrazumevane konfiguracije
koje možete prilagoditi po potrebi. Ovo značajno smanjuje količinu koda koji pišete, jer
aplikacije slede ustaljene konvencije, a vi menjate samo ono što se razlikuje. Umesto da
pišete sve konfiguracije ispočetka za svaku aplikaciju, efikasnije je početi sa podrazumevanim
podešavanjima i menjati samo ono što je potrebno. O Spring Boot-u ćemo detaljnije govoriti
od lekcije 6.
Spring ekosistem je veoma širok i sadrži mnoge projekte. Neki se koriste češće od drugih, dok
se neki možda nikada ne koriste, zavisno od potreba aplikacije koju gradite. Kompletnu listu
projekata koji su deo Spring ekosistema možete pronaći na zvaničnom sajtu: https://spring.io/
projects.
10
Poglavlje 2 Spring ekosistem
ALTERNATIVE ZA KORIŠĆENJE SPRING-A
Za mnoge pojedinačne komponente i projekte koji čine Spring
ekosistem, postoje druge opcije—bilo da su open-source ili komercijalni
okviri i biblioteke.
Ne možemo u potpunosti govoriti o alternativama za Spring, jer bi to moglo biti pogrešno
shvaćeno kao alternative za ceo ekosistem. Međutim, za mnoge pojedinačne komponente
i projekte koji čine Spring ekosistem, postoje druge opcije—bilo da su open-source ili
komercijalni okviri i biblioteke.
Na primer, uzmimo Spring IoC kontejner. Godinama unazad, Java EE specifikacija je bila
popularno rešenje među programerima. Sa nešto drugačijom filozofijom, Java EE (koji je
2017. godine postao open-source i preimenovan u Jakarta EE, https://jakarta.ee/ nudio je
specifikacije poput:
• Context and Dependency Injection (CDI)
• Enterprise Java Beans (EJB)
Pomoću CDI ili EJB-a, mogli ste upravljati kontekstom instanci objekata i implementirati
aspekte ( interceptors, prema EE terminologiji). Takođe, kroz istoriju, Google Guice
(https://github.com/google/guice) bio je cenjen okvir za upravljanje instancama objekata
unutar kontejnera.
Za neke pojedinačne Spring projekte možete pronaći jednu ili više alternativa. Na primer:
• Umesto Spring Security, možete koristiti Apache Shiro (https://shiro.apache.org/)
• Umesto Spring MVC, možete koristiti Play Framework (https://www.playframework.com/).
Savet je da uvek uzmete u obzir alternative. U softverskom razvoju, važno je imati otvoren
um i nikada ne smatrati jedno rešenje kao apsolutno najbolje. Uvek postoje scenariji u kojima
će određena tehnologija biti bolji izbor od druge.
11
Poglavlje 3
Spring u scenarijima iz stvarnog
sveta
PRIMERI UPOTREBE SPRING-A
Spring se generalno pokazao kao dobro rešenje za: razvoj backend
aplikacija, okvira za automatizovano testiranje, desktop i mobilnih
aplikacija.
Sada kada imate pregled Spring-a, proćićemo različite scenarije primene u kojima korišćenje
Spring okvira može biti odličan izbor. Često se korišćenje okvira poput Spring-a povezuje
isključivo sa razvojem backend aplikacija. Još češće, ograničavaju njegovu primenu samo
na backend web aplikacije. Iako je tačno da se Spring često koristi na ovaj način, važno je
zapamtiti da nije ograničen samo na ovaj scenario.
Spring se može koristiti u različitim vrstama aplikacija, uključujući razvoj aplikacija za
automatizovano testiranje ili čak samostalnih desktop aplikacija.
U sledećim slučajevima Spring se generalno pokazao kao dobro rešenje:
1. Razvoj backend aplikacije
2. Razvoj okvira za automatizovano testiranje
3. Razvoj desktop aplikacije
4. Razvoj mobilne aplikacije
KORIŠĆENJE SPRING-A U RAZVOJU BACKEND
APLIKACIJE
Backend aplikacija je deo sistema koji se izvršava na serverskoj strani i
ima odgovornost da upravlja podacima i obrađuje zahteve klijentskih
aplikacija.
Backendaplikacija je deo sistema koji se izvršava na serverskoj strani i ima odgovornost
da upravlja podacima i obrađuje zahteve klijentskih aplikacija. Korisnici pristupaju
funkcionalnostima sistema pomoću klijentskih aplikacija, koje zatim šalju zahteve ka
backendaplikaciji radi obrade korisničkih podataka. Backendaplikacija može koristiti baze
podataka za skladištenje podataka ili komunicirati sa drugim backend aplikacijama na
različite načine. Možete zamisliti stvarni scenario u kojem aplikacija predstavlja backend
sistem za upravljanje transakcijama na vašem bankovnom računu. Korisnici mogu pristupiti
svojim računima i upravljati njima putem web aplikacije (internet bankarstvo) ili mobilne
12
Poglavlje 3 Spring u scenarijima iz stvarnog sveta
aplikacije. U ovom slučaju, mobilne i web aplikacije su klijenti backend aplikacije. Da bi
upravljala transakcijama korisnika, backend aplikacija mora komunicirati sa drugim backend
sistemima, a deo podataka koje obrađuje mora biti perzistiran u bazi podataka.
Na slici 3.1 možete videti arhitekturu ovakvog sistema gde se može videti kako backend
aplikacija komunicira na više načina sa drugim aplikacijama i koristi baze podataka za
upravljanje podacima. Obično je backend aplikacija složena i može zahtevati korišćenje
različitih tehnologija. Okviri pojednostavljuju implementaciju pružanjem alata koje možete
koristiti za bržu implementaciju backend rešenja.
Slika 3.1 aplikacija koja komunicira na više načina sa drugim aplikacijama i koristi baze podataka za
upravljanje podacima. Izvor: autor
MOGUĆA ARHITEKTURA SISTEMA KOJI U BACKEND
APLIKACIJAMA KORISTI SPRING
Spring nudi odličan set alata za implementaciju backend aplikacija.
Spring nudi odličan set alata za implementaciju backendaplikacija. Olakšava razvoj pružajući
različite funkcionalnosti koje su obično potrebne u backend rešenjima, od integracije sa
drugim aplikacijama do perzistencije podataka u različitim bazama podataka. Nije
iznenađujuće što programeri često koriste Spring za ovakve aplikacije. Okvir u suštini pruža
sve što vam je potrebno za implementaciju backendrešenja i odlično se uklapa u bilo koji
arhitektonski stil. Na slici 3.2 prikazane su mogućnosti korišćenja Spring-a u backend
aplikacijama od izlaganja funkcionalnosti koje druge aplikacije mogu pozivati, do upravljanja
pristupom bazi podataka, osiguravanja aplikacije i integracije putem eksternih message
broker-a trećih strana.
13
Poglavlje 3 Spring u scenarijima iz stvarnog sveta
Slika 3.2 Mogućnosti korišćenja Spring-a u backend aplikacijama Izvor: autor
KORIŠĆENJE SPRING-A U APLIKACIJI ZA
AUTOMATIZOVANO TESTIRANJE
Automatizovano testiranje podrazumeva implementaciju softvera koji
razvojni timovi koriste kako bi osigurali da se aplikacija ponaša prema
očekivanjima.
Danas se automatizovano testiranje često koristi za end-to-endtestiranje sistema koje
implementiramo. Automatizovano testiranje podrazumeva implementaciju softvera koji
razvojni timovi koriste kako bi osigurali da se aplikacija ponaša prema očekivanjima. Razvojni
tim može podesiti aplikaciju za automatizovano testiranje tako da redovno testira aplikaciju
i obaveštava programere ako nešto nije u redu. Ovakva funkcionalnost daje programerima
sigurnost jer znaju da će biti obavešteni ako prilikom dodavanja novih funkcionalnosti
nehotice pokvare postojeće mogućnosti aplikacije. Dok je u malim sistemima moguće obaviti
testiranje ručno, uvek je dobra praksa automatizovati test slučajeve. U složenijim sistemima,
ručno testiranje svih tokova jednostavno nije opcija. Zbog velikog broja različitih tokova, bilo
bi potrebno previše sati i resursa da bi se svi scenariji pokrili ručno. Najefikasnije rešenje
u takvim slučajevima jeste da se poseban tim posveti razvoju aplikacije koja ima zadatak
da validira sve tokove testiranog sistema. Kako programeri dodaju nove funkcionalnosti u
sistem, aplikacija za testiranje se stalno unapređuje kako bi pokrila te promene. Timovi je
koriste za proveru ispravnosti sistema, osiguravajući da sve i dalje funkcioniše kako treba. Na
kraju, programeri koriste alat za integraciju i podešavaju aplikaciju da se redovno pokreće,
omogućavajući im da što pre dobiju povratne informacije o promenama koje su napravili (slika
3.3).
Slika 3.3 prikazuje tim koji postavlja aplikaciju za testiranje u testnom okruženju. Alat za
kontinuiranu integraciju poput Jenkinsa regularno izvršava aplikaciju i šalje povratne
informacije timu. Na taj način, tim je uvek upoznat sa statusom sistema i zna kada nešto
pokvari tokom razvoja.
14
Poglavlje 3 Spring u scenarijima iz stvarnog sveta
Slika 3.3 Okruženje za testiranje aplikacija Izvor: autor
MOGUĆA ARHITEKTURA SISTEMA KOJI U
APLIKACIJAMA ZA TESTIRANJE KORISTI SPRING
Ponekad aplikacija za testiranje simulira spoljne zavisnosti (mockuje ih)
kako bi testirala različite scenarije izvršavanja.
Aplikacija za tesitranje može postati jednako složena kao i backend aplikacija. Da bi validirala
tokove, aplikacija mora komunicirati sa komponentama sistema, pa čak i povezivati se sa
bazama podataka. Ponekad aplikacija simulira spoljne zavisnosti (mockuje ih) kako bi testirala
različite scenarije izvršavanja. Za pisanje testnih scenarija programeri koriste okvire poput
Selenium-a, Cucumber-a, Gauge-a i drugih. Međutim, čak i uz ove alate, aplikacija može imati
značajne koristi od Spring alata. Na primer, aplikacija može:
• Upravljati instancama objekata pomoću Spring IoC kontejnera, što olakšava održavanje
koda.
• Koristiti Spring Data za povezivanje sa bazama podataka radi provere podataka.
• Slati poruke u redove ili teme brokerskog sistema kako bi simulirala specifične scenarije.
• Koristiti Spring za pozivanje REST endpoint-a radi provere interakcije sa API-jem.
Aplikacija za testiranje može imati potrebu da se poveže sa bazama podataka ili komunicira
sa drugim sistemima ili sa samim testiranim sistemom. Programeri mogu koristiti
komponente Spring ekosistema kako bi pojednostavili implementaciju ovih funkcionalnosti.
15
Poglavlje 3 Spring u scenarijima iz stvarnog sveta
Slika 3.4 Arhitektura aplikacije za automatizovano testiranje Izvor: autor
KORIŠĆENJE SPRING-A ZA RAZVOJ DESKTOP I
MOBILNIH APLIKACIJA
Danas se desktop aplikacije ne razvijaju tako često, jer su web i
mobilne aplikacije preuzele glavnu ulogu u interakciji sa korisnicima.
Danas se desktop aplikacije ne razvijaju tako često, jer su web i mobilne aplikacije preuzele
glavnu ulogu u interakciji sa korisnicima. Međutim, i dalje postoji manji broj desktop
aplikacija, a komponente Spring ekosistema mogu biti dobar izbor za implementaciju njihovih
funkcionalnosti. Desktop aplikacija može uspešno koristiti Spring IoC kontejner za upravljanje
instancama objekata, čime se postiže čistiji kod i bolja održivost aplikacije. Pored toga,
aplikacija može koristiti Spring alate za implementaciju različitih funkcionalnosti, na primer:
• Komunikacija sa backend-om ili drugim komponentama (pozivanje web servisa ili
korišćenje drugih tehnika za udaljene pozive).
• Implementacija keširanja radi poboljšanja performansi aplikacije.
Spring zajednica je putem projekta Spring for Android (https://spring.io/projects/springandroid) nastojala da podrži razvoj mobilnih aplikacija. Iako ćete retko naići na ovakvu
situaciju, vredi napomenuti da je moguće koristiti Spring alate u razvoju Android aplikacija.
Ovaj Spring projekat nudi:
• REST klijent za Android
• Podršku za autentifikaciju prilikom pristupa zaštićenim API-jevima.
16
Poglavlje 3 Spring u scenarijima iz stvarnog sveta
KADA NE KORISTITI APLIKACIONE OKVIRE
Ponekad upotreba alata koji je previše složen za dati zadatak može
dovesti do veće potrošnje energije i lošijih rezultata.
Iako su softverski okviri ( frameworks) moćan alat, postoje situacije kada njihova primena
može biti neefikasna ili čak štetna za projekat. Važno je znati ne samo kada koristiti okvir,
već i kada ga treba izbeći. U nastavku su četiri tipične situacije u kojima korišćenje okvira nije
preporučljivo:
• Kada aplikacija mora imati mali memorijski otisak. Ako razvijate aplikaciju koja
mora biti što manja i brža za pokretanje – kao što je slučaj sa kontejnerizovanim
servisima ili serverlessfunkcijama – dodatne zavisnosti koje okvir uvodi mogu značajno
povećati veličinu aplikacije. U takvim okruženjima prednost imaju aplikacije sa
minimalnim brojem biblioteka, jer brže startuju i efikasnije koriste resurse. U tim
slučajevima, bolje je koristiti „lakši“ pristup bez punog okvira.
• Kada bezbednosni zahtevi ne dozvoljavaju korišćenje open-source rešenja. U
osetljivim domenima kao što su odbrana, zdravstvo ili državne institucije, često se
postavljaju strogi bezbednosni zahtevi. Upotreba open-sourceokvira, kao što je Spring,
može biti rizična jer eventualni propusti mogu biti javno poznati. U tim slučajevima
se bira ručno implementirano rešenje kako bi se imala potpuna kontrola nad kodom i
smanjio rizik od napada. Iako je open-source često bezbedan, za maksimalnu sigurnost
ponekad je bolje koristiti sopstveni kod.
• Kada okvir zahteva previše prilagođavanja. Ako morate prilagođavati gotovo svaki
deo okvira kako bi odgovarao vašim potrebama, postoji velika šansa da okvir više smeta
nego što pomaže. U takvim slučajevima, možda je efikasnije izgraditi sopstveno rešenje
„od nule“, jer ćete uz manje koda dobiti jednostavniji i pregledniji sistem. Okviri treba da
olakšaju razvoj, a ne da ga zakomplikuju.
• Kada ne postoji stvarna korist od korišćenja okvira. Ponekad se tim odluči da
uvede popularan okvir samo zato što ga „svi koriste“, bez prethodne analize koristi. Ako
aplikacija već radi stabilno, a okvir ne donosi poboljšanje u održavanju, performansama
ili bezbednosti, prelazak je nepotreban i može izazvati dodatne komplikacije. Uvođenje
okvira ima smisla samo ako donosi jasnu vrednost.
Okviri su korisni, ali nisu univerzalno rešenje. Pre njihove upotrebe treba pažljivo razmotriti
kontekst projekta, tehničke zahteve i stvarne koristi. U nekim slučajevima, jednostavniji i lakši
pristup daje bolje rezultate.
17
Poglavlje 4
Spring kontekst
SPRING KONTEKST: DEFINISANJE OBJEKATA KOJE
SPRING UPRAVLJA (ENGL. BEANS)
Spring kontekst je mesto gde Spring drži i upravlja objektima. Da bi
neki objekat bio "pod kontrolom" Springa, morate ga dodati u kontekst.
Spring kontekst je mesto gde Spring drži i upravlja objektima. Da bi neki objekat bio "pod
kontrolom" Springa, morate ga dodati u kontekst. Time dobijate pristup svim prednostima
koje Spring nudi – automatsko upravljanje zavisnostima, integraciju funkcionalnosti,
jednostavnije testiranje i više. Bez konteksta, nema ni pravog korišćenja Springa.
Spring kontekst ( application context) predstavlja centralno mesto u memoriji aplikacije u
kojem se nalaze svi objekti (tzv. bean-ovi) koje Spring okvir upravlja. Možete ga zamisliti kao
poseban deo memorije u kojem Spring čuva objekte (instance klasa) koje treba da koristi i
kojima upravlja u toku rada aplikacije.
Po prirodi, Spring ne zna ništa o klasama i objektima koje definišemo u aplikaciji. Spring sam
po sebi ne zna ništa o klasama koje vi napišete – dok mu ih eksplicitno ne „prijavite“. To
znači da morate jasno reći Springu: „Ova instanca mi je važna – upravljaj njom!“ Kada jednom
stavite bean u kontekst, Spring preuzima kontrolu nad njegovim životnim ciklusom: pravi
ga, povezuje ga sa drugim komponentama, i omogućava vam da koristite različite napredne
funkcionalnosti – kao što su transakcije, povezivanje sa bazom, testiranje i još mnogo toga.
Kontekst je osnova kroz koju se aktiviraju sve ključne mogućnosti Springa. Ako objekat nije
registrovan u kontekstu, Spring ga ne vidi i ne može da ga koristi. Ti objekti koje Spring
upravlja nazivaju se bean-ovi. Ne moraju svi objekti aplikacije biti deo konteksta – samo oni
koji treba da budu pod kontrolom Springa. Za rad sa kontekstom važno je znati kako se
objekti dodaju i kako se među njima uspostavljaju odnosi. Na taj način, aplikacija koristi pun
potencijal Spring okvira.
KREIRANJE MAVEN PROJEKTA
Maven nije direktno povezan sa Spring-om, ali je alat koji omogućava
lakše upravljanje procesom izgradnje aplikacije, bez obzira na okvir
koji koristite.
Maven nije direktno povezan sa Spring-om, ali je alat koji omogućava lakše upravljanje
procesom izgradnje aplikacije, bez obzira na okvir koji koristite. Morate znati osnove Maven
projekata kako biste mogli pratiti kodne primere u ovoj knjizi. Maven je jedan od najčešće
18
Poglavlje 4 Spring kontekst
korišćenih alata za izgradnju Spring projekata u realnim scenarijima. Gradle je još jedan
poznati alat, ali o njemu nećemo govoriti u ovoj knjizi. Ako već znate kako da kreirate Maven
projekat i dodate zavisnosti u njegovu konfiguraciju, možete preskočiti ovu sekciju i preći
direktno na sledeći deo.
Alat za izgradnju ( build tool) je softver koji koristimo kako bismo olakšali proces razvoja
aplikacija. Konfigurišemo ga tako da automatizuje zadatke koji su deo izgradnje aplikacije,
umesto da ih radimo ručno. Tipični zadaci koji se često nalaze u procesu izgradnje aplikacije
uključuju preuzimanje zavisnosti, pokretanje testova, validaciju sintakse, proveru
bezbednosnih ranjivosti, kompilaciju aplikacije i pakovanje aplikacije u izvršivu arhivu. Kako
bismo u našim primerima lako upravljali zavisnostima, potrebno je koristiti alat za izgradnju.
Ova sekcija vas uči samo ono što vam je potrebno za rad sa primerima u knjizi. Korak po
korak ćemo proći kroz proces kreiranja Maven projekta i objasniti osnovne elemente njegove
strukture.
Kao i kod razvoja bilo koje aplikacije, potrebno je koristiti razvojno okruženje (IDE). Danas
svaki profesionalni IDE pruža podršku za Maven projekte, tako da možete koristiti bilo koji po
vašem izboru: IntelliJ IDEA, Eclipse, Spring STS, NetBeans ili neki drugi.
Na ovom predmetu koristimo IntelliJ IDEA, ali ne brinite—struktura Maven projekta je ista
bez obzira na to koji IDE koristite. Sa vašim studentskim nalozima možete preuzeti Ultimate
verziju ovog razvojnog okruženja besplatno.
Da biste kreirali novi Maven projekat u IntelliJ IDEA, idite na File > New > Project. Ova akcija
će vas dovesti do ekrana poput onog prikazanog na slici 2.1.
Slika 4.1 Kreiranje novog Maven projekta Izvor: [autor]
STRUKTURA MAVEN PROJEKTA
Struktura Maven projekta ne zavisi od IDE-a koji koristite za razvoj
aplikacija.
19
Poglavlje 4 Spring kontekst
Nakon što ste izabrali tip projekta, u sledećem prozoru (slika 4.2) treba da mu dodelite ime.
Pored imena projekta i izbora lokacije gde će biti sačuvan, u Maven projektu možete dodatno
definisati sledeće:
• Group ID, koji koristimo za grupisanje više povezanih projekata.
• Artifact ID, koji predstavlja naziv trenutne aplikacije.
• Version, koja služi kao identifikator trenutnog stanja implementacije.
U stvarnim aplikacijama, ova tri atributa su ključni detalji i važno je da ih pravilno definišete.
Struktura Maven projekta ne zavisi od IDE-a koji koristite za razvoj aplikacija. Kada prvi put
pogledate svoj Maven projekat, primetićete dva glavna elementa:
• “src” folder (poznat i kao sourcefolder), u kojem ćete smeštati sav kod i resurse
aplikacije.
• pom.xml fajl, u kojem definišete konfiguracije Maven projekta, poput dodavanja novih
zavisnosti.
Maven organizuje “src” folder u sledeće podfoldere:
• “main” folder, gde se čuva izvorni kod aplikacije. Ovaj folder sadrži dva posebna
podfoldera: “java”, koji sadrži Java kod aplikacije i “resources”, gde se nalaze
konfiguracioni fajlovi aplikacije.
• “test” folder, gde se skladišti izvorni kod jediničnih testova.
Slika 4.2 Podešavanje maven projekta Izvor: autor
SADŽAJ POM.XML-A
Da bismo dodali ove zavisnosti u Maven projekte, potrebno je da
izmenimo sadržaj pom.xml fajla.
20
Poglavlje 4 Spring kontekst
U pom.xml fajlu pišemo konfiguracije za Maven projekat (u našim primerima, prvenstveno
ćemo ga koristiti za definisanje zavisnosti). U projektima koje kreiramo koristićemo veliki broj
spoljnih zavisnosti—biblioteka ili okvira koji nam pomažu u implementaciji funkcionalnosti
u primerima. Da bismo dodali ove zavisnosti u Maven projekte, potrebno je da izmenimo
sadržaj pom.xml fajla. U sledećem listingu prikazan je podrazumevani sadržaj pom.xml fajla
odmah nakon kreiranja Maven projekta.
<?xml version="1.0" encoding="UTF-8"?>
<project
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>sq-ch2-ex1</artifactId>
<version>1.0-SNAPSHOT</version>
</project>
Sa ovim pom.xml fajlom, projekat ne koristi nijednu spoljnju zavisnost. Ako pogledate folder
sa spoljnim zavisnostima projekta, trebalo bi da vidite samo JDK (slika 4.3).
Slika 4.3 Podrazumevana eksterna zavisnost sa inicijalnim pom.xml-om Izvor: autor
Sa podrazumevanim pom.xml fajlom, vaš projekat koristi samo JDK kao spoljašnju zavisnost.
Jedan od glavnih razloga za izmenu pom.xml fajla jeste dodavanje novih zavisnosti koje su
potrebne vašoj aplikaciji.
DODAVANJE NOVIH ZAVISNOSTI U PROJEKAT
Sve zavisnosti se pišu unutar <dependencies>...</dependencies>
tagova.
21
Poglavlje 4 Spring kontekst
Sledeći listing prikazuje kako dodati spoljašnje zavisnosti u vaš projekat. Sve zavisnosti se
pišu unutar <dependencies>...</dependencies> tagova. Svaka zavisnost je predstavljen
a <dependency>...</dependency> grupom tagova, unutar kojih definišete njene
atribute:
• Group ID – identifikator grupe kojoj zavisnost pripada
• Artifact name – naziv zavisnosti
• Version – verzija zavisnosti
Maven će pretražiti repozitorijum koristeći ove tri vrednosti i preuzeti zavisnosti u vaš
projekat.
<?xml version="1.0" encoding="UTF-8"?>
<project
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>sq_ch2_ex1</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.6.RELEASE</version>
</dependency>
</dependencies>
</project>
Nećemo ulaziti u detalje o tome kako konfigurisati prilagođeni repozitorijum, ali je važno znati
da Maven podrazumevano preuzima zavisnosti iz centralnog Maven repozitorijuma (Maven
Central). Preuzeti jar fajlovi mogu se pronaći u folderu spoljašnjih zavisnosti vašeg projekta,
kao što je prikazano na slici 4.4. Kada dodate novu zavisnost u pom.xml fajl, Maven preuzima
jar fajlove koji predstavljaju tu zavisnost. Ove jar fajlove možete pronaći u folderu External
Libraries unutar vašeg projekta.
22
Poglavlje 4 Spring kontekst
Slika 4.4 Prikaz novih zavisnosti koje su preuzete nakon podešavanja pom.xml-a Izvor: autor
23
Poglavlje 5
Dodavanje novih bean-ova u
Spring kontekst
DODAVANJE NOVIH BEAN-OVA
Postoje različiti načini za dodavanje bean-ova, kako bi ih Spring mogao
upravljati i povezivati sa funkcionalnostima koje pruža.
U ovom delu naučićete kako dodati nove instance objekata (bean-ove) u Spring kontekst.
Videćete da postoje različiti načini za dodavanje bean-ova, kako bi ih Spring mogao upravljati
i povezivati sa funkcionalnostima koje pruža. Zavisno od situacije, biraćete određeni način
dodavanja bean-a. Objasnićemo kada koristiti koji pristup. Možete dodati bean-ove u kontekst
na sledeće načine:
• Korišćenjem @Bean anotacije
• Korišćenjem stereotipnih anotacija
• Programski (manualno dodavanje)
Za početak, kreiraćemo projekat bez referenci na bilo koji okvir, pa čak ni na Spring. Zatim
ćemo dodati zavisnosti potrebne za korišćenje Spring konteksta i kreirati ga (slika 5.1). Prvo
kreiramo Maven projekat i definišemo klasu.
Slika 5.1.1 Za početak, kreiramo instancu objekta i prazan Spring kontekst. Izvor: autor
Upotrebićemo klasu pod nazivom Parrot, koja će imati jedan String atribut, predstavljajući ime
papagaja:
24
Poglavlje 5 Dodavanje novih bean-ova u Spring kontekst
public class Parrot {
private String name;
// Omitted getters and setters
}
REGISTRACIJA NOVIH BEAN-OVA U MAIN KLASI
Klasa AnnotationConfigApplicationContext se koristi za kreiranje
instance Spring konteksta.
Sada možete definisati klasu koja sadrži main metodu i kreirati instancu klase Parrot, kao što
je prikazano u sledećem listingu:
public class Main {
public static void main(String[] args) {
Parrot p = new Parrot();
}
}
Sada je vreme da dodamo potrebne zavisnosti u naš projekat. Pošto koristimo Maven,
dodaćemo zavisnosti u pom.xml fajl, kao što je prikazano u sledećem listingu.
<project
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/
maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>sq-ch2-ex1</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.6.RELEASE</version>
</dependency>
</dependencies>
</project>
Jedna ključna stvar koju treba primetiti je da je Spring dizajniran kao modularan okvir. To
znači da ne morate dodavati ceo Spring ekosistem u svoju aplikaciju kada koristite neku
njegovu komponentu. Umesto toga, dodajete samo one delove koji su vam potrebni. Zbog
toga, u listingu videćete samo zavisnost spring-context. Ovo govori Maven-u da preuzme
samo potrebne zavisnosti za korišćenje Spring konteksta. Tokom ovog predmeta dodavaćemo
različite zavisnosti u naše projekte u zavisnosti od onoga što implementiramo, ali ćemo uvek
dodavati samo ono što nam je potrebno.
25
Poglavlje 5 Dodavanje novih bean-ova u Spring kontekst
Nakon što smo dodali potrebnu zavisnost u naš projekat, sada možemo kreirati instancu
Spring
konteksta.
U
sledećem
listingu
videćete
kako
koristimo
klasu
AnnotationConfigApplicationContext za kreiranje instance Spring konteksta.
public class Main {
public static void main(String[] args) {
var context =
new AnnotationConfigApplicationContext();
Parrot p = new Parrot();
}
}
Spring nudi više implementacija konteksta, ali pošto se u većini slučajeva koristi
AnnotationConfigApplicationContext (implementacija zasnovana na anotacijama, što je
danas najčešći pristup), fokusiraćemo se na nju.
Slika 5.1.2 Šta je postignuto, šta dalje želimo? Izvor: autor
5.1 Korišćenje Bean anotacije
KORIŠĆENJE @BEAN ANOTACIJE
Zapamtite da učite kako da dodate bean-ove u Spring kontekst jer
Spring može upravljati samo objektima koji su deo konteksta.
Prvi način dodavanja instance objekta u Spring kontekst pomoću @Bean anotacije. Ovim
pristupom možete dodati instance klasa definisanih u vašem projektu (kao što je Parrot u
našem primeru), ali i klase koje niste sami kreirali, već ih koristite u aplikaciji. Verujem da je
ovaj pristup najlakši za razumevanje kada tek počinjete sa učenjem Spring-a. Zapamtite da
učite kako da dodate bean-ove u Spring kontekst jer Spring može upravljati samo objektima
koji su deo konteksta. Prvo ću vam pokazati jednostavan primer dodavanja bean-a u Spring
kontekst koristeći @Bean anotaciju. Zatim ću vam prikazati kako da dodate više bean-ova
istog ili različitog tipa. Koraci koje treba pratiti da biste dodali bean u Spring kontekst pomoću
@Bean anotacije su sledeći (slika 6.1):
26
Poglavlje 5 Dodavanje novih bean-ova u Spring kontekst
• Definišite konfiguracionu klasu (označenu sa@Configuration) za vaš projekat, koju
koristimo za podešavanje Spring konteksta. O tome ćemo detaljnije govoriti kasnije.
• Dodajte metodu u konfiguracionu klasu koja vraća instancu objekta koji želite da dodate
u kontekst i označite tu metodu anotacijom @Bean.
• Omogućite Spring-u da koristi konfiguracionu klasu definisanu u koraku 1. Kao što ćete
kasnije naučiti, koristimo konfiguracione klase za podešavanje različitih aspekata Spring
okvira.
Slika 5.2.1 Korišćenje @Bean anotacije za dodavanje instance u Spring kontekst Izvor: [1]
KORACI ZA KORIŠĆENJE @BEAN ZA DODAVANJE INSTANCE
OBJEKTA U SPRING KONTEKST
Prvi korak je kreiranje konfiguracione klase u projektu. Drugi korišćenje
@Bean i treći osiguravanje da Spring koristi konfiguracionu klasu.
KORAK 1: DEFINISANJE KONFIGURACIONE KLASE U PROJEKTU
Prvi korak je kreiranje konfiguracione klase u projektu. Spring konfiguraciona klasa je
prepoznatljiva po tome što je označena anotacijom @Configuration. Koristimo konfiguracione
klase za definisanje različitih Spring konfiguracija unutar projekta. Sledeći listing prikazuje
kako definisati konfiguracionu klasu.
@Configuration
public class ProjectConfig {}
NAPOMENA: Razdvajam klase u različite pakete kako bi kod bio lakši za razumevanje. Na
primer, kreiramo konfiguracione klase u paketu config, dok Main klasu smeštamo u paket
main.
KORAK 2: KREIRANJE METODE KOJA VRAĆA BEAN I ANOTACIJA @BEAN
27
Poglavlje 5 Dodavanje novih bean-ova u Spring kontekst
Jedna od stvari koju možete uraditi sa konfiguracionom klasom je dodavanje bean-ova u
Spring kontekst. Da biste to uradili, potrebno je da definišete metodu koja vraća instancu
objekta koji želite da dodate u kontekst i da tu metodu označite anotacijom @Bean. Anotacija
@Bean omogućava Spring-u da zna da treba da pozove ovu metodu prilikom inicijalizacije
svog konteksta i da vrednost koju metoda vrati doda u kontekst. Sledeći listing prikazuje
izmenu konfiguracione klase da bi se implementirao ovaj korak.
@Configuration
public class ProjectConfig {
@Bean
Parrot parrot() {
var p = new Parrot();
p.setName("Koko");
return p;
}
}
Verovatno ste naučili da je Java best practice da imena metoda sadrže glagole, jer metode
obično predstavljaju akcije. Međutim, za metode koje koristimo da dodamo bean-ove u Spring
kontekst i koje predstavljaju objektne instance koje vraćaju, a koje će sada biti deo Spring
konteksta ne pratimo ovu konvenciju Takođe, ime metode postaje i ime bean-a. Po konvenciji,
možete koristiti imenice, a najčešće se koristi isto ime kao i klasa.
KORAK 3: OMOGUĆAVANJE SPRING-U DA INICIJALIZUJE KONTEKST KORIŠĆENJEM
KONFIGURACIONE KLASE
Implementirali smo konfiguracionu klasu u kojoj Spring-u govorimo koju instancu objekta
treba dodati kao bean. Sada moramo osigurati da Spring koristi ovu konfiguracionu klasu
prilikom inicijalizacije svog konteksta. Sledeći listing prikazuje kako da izmenite instanciranje
Spring konteksta u glavnoj klasi, tako da koristi konfiguracionu klasu koju smo implementirali
u prva dva koraka. Da biste proverili da li je instanca Parrot zaista deo Spring konteksta,
možete se pozvati na instancu i odštampati " Koko" u konzoli, kao što je prikazano u u istom
listingu.
public class Main {
public static void main(String[] args) {
var context =
new AnnotationConfigApplicationContext(
ProjectConfig.class);
Parrot p = context.getBean(Parrot.class);
System.out.println(p.getName());
}
}
PRIMER: DODAVANJE OBJEKATA STRING I INTEGER U SPRING
KONTEKST
Možete dodati bilo koju vrstu objekata u Spring kontekst
28
Poglavlje 5 Dodavanje novih bean-ova u Spring kontekst
Kao u prethodnom primeru, možete dodati bilo koju vrstu objekata u Spring kontekst (slika
6.2). Hajde da dodamo i String i Integer, i proverimo kako to funkcioniše. Sledeći listing
prikazuje kako sam izmenio konfiguracionu klasu da bih dodao još dva bean-a:
• Bean tipa String
• Bean tipa Integer.
@Configuration
public class ProjectConfig {
@Bean
Parrot parrot() {
var p = new Parrot();
p.setName("Koko");
return p;
}
@Bean
String hello() {
return "Hello";
}
@Bean
Integer ten() {
return 10;
}
NAPOMENA: Zapamtite svrhu Spring konteksta—dodajemo instance koje očekujemo da
će Spring upravljati. (Na taj način povezujemo aplikaciju sa funkcionalnostima koje okvir
pruža.)
U stvarnim aplikacijama, nećemo dodavati svaki objekat u Spring kontekst.. Kada naši primeri
budu bliži produkcijskom kodu, više ćemo se fokusirati na to koje objekte Spring zaista treba
da upravlja. Sada možemo referencirati ova dva nova bean-a na isti način kao što smo to
uradili sa parrot objektom. Sledeći listing prikazuje izmenjenu main metodu tako da ispiše
vrednosti novih bean-ova.
Slika 5.2.2 Dodavanje više objekata u Spring kontekst Izvor: autor
29
Poglavlje 5 Dodavanje novih bean-ova u Spring kontekst
public class Main {
public static void main(String[] args) {
var context = new AnnotationConfigApplicationContext(
ProjectConfig.class);
Parrot p = context.getBean(Parrot.class);
System.out.println(p.getName());
String s = context.getBean(String.class);
System.out.println(s);
Integer n = context.getBean(Integer.class);
System.out.println(n);
}
}
Pokretanjem aplikacije sada će se u konzoli ispisati vrednosti tri bean-a, kao što je prikazano
u sledećem isečku koda:
Koko
Zdravo
10
DODAVANJE VIŠE OBJEKATA ISTOG TIPA U SPRING KONTEKST
Podrazumevano, Spring koristi imena metoda anotiranih sa @Bean kao
imena bean-ova i na taj način možemo odrediti koji tačno želimo da
koristimo.
Hajde da kreiramo novi projekat, kako bismo demonstrirali kako dodati više bean-ova istog
tipa u Spring kontekst i kako ih kasnije referencirati. Sledeći listing prikazuje novu
konfiguracionu klasu:
@Configuration
public class ProjectConfig {
@Bean
Parrot parrot1() {
var p = new Parrot();
p.setName("Koko");
return p;
}
@Bean
Parrot parrot2() {
var p = new Parrot();
p.setName("Miki");
return p;
}
@Bean
Parrot parrot3() {
var p = new Parrot();
p.setName("Riki");
return p;
30
Poglavlje 5 Dodavanje novih bean-ova u Spring kontekst
}
}
Naravno, više ne možete dobiti bean-ove iz konteksta samo navodeći njihov tip. Ako pokušate
da to uradite, dobićete izuzetak, jer Spring ne može sam da pretpostavi na koju instancu
mislite. Pogledajte sledeći listing. Pokretanjem ovakvog koda dobićete izuzetak
NoUniqueBeanDefinitionException, u kojem vam Spring jasno govori da morate
precizirati koju instancu želite da koristite.
public class Main {
public static void main(String[] args) {
var context = new
AnnotationConfigApplicationContext(ProjectConfig.class);
Parrot p = context.getBean(Parrot.class);
System.out.println(p.getName());
}
}
Da biste rešili ovaj problem dvosmislenosti, morate precizno referencirati jednu od instanci
koristeći ime bean-a. Podrazumevano, Spring koristi imena metoda anotiranih sa @Bean kao
imena bean-ova. Zato metode anotirane sa @Bean ne nazivamo glagolima, već imenima koja
predstavljaju sam objekat. U našem slučaju, bean-ovi imaju imena: parrot1, parrot2 i parrot3
(zapamtite, ime metode predstavlja bean). Pravilno definisan Main bi bio:
public class Main {
public static void main(String[] args) {
var context = new AnnotationConfigApplicationContext(ProjectConfig.class);
Parrot p = context.getBean("parrot2", Parrot.class);
System.out.println(p.getName());
}
}
Ako želite da dodelite drugo ime bean-u, možete koristiti jedan od atributa anotacije @Bean:
name ili value. Bilo koja od sledećih sintaksi promeniće ime bean-a u "miki":
• @Bean(name = "miki")
• @Bean(value = "miki")
• @Bean("miki")
U sledećem listingu možete videti kako se ova promena primenjuje u kodu.
@Bean(name = "miki")
Parrot parrot2() {
var p = new Parrot();
p.setName("Miki");
return p;
}
31
Poglavlje 5 Dodavanje novih bean-ova u Spring kontekst
Međutim, postoji još jedna opcija kada imate više bean-ova istog tipa u kontekstu. Možete
označiti jedan od njih kao primarni pomoću @Primary anotacije. Primarni bean je onaj koji će
Spring automatski izabrati ako postoji više opcija istog tipa, a vi ne navedete ime bean-a.
@Bean
@Primary
Parrot parrot2() {
var p = new Parrot();
p.setName("Miki");
return p;
}
5.2 Korišćenje stereotipnih anotacija
KORIŠĆENJE STEREOTIPNIH ANOTACIJA ZA DODAVANJE BEAN-OVA
U SPRING KONTEKST
Pomoću stereotipnih anotacija moguće je napisati manje koda da bi se
bean dodao u kontekst.
Korišćenje stereotipnih anotacija, kao što je @Component, predstavlja alternativni način
dodavanja bean-ova u Spring kontekst u odnosu na@Bean anotaciju. Ovaj pristup
omogućava jednostavnije dodavanje bean-ova uz manje koda. Anotacija se postavlja iznad
klase, čime se ona označava kao komponenta koju Spring automatski instancira i dodaje
u kontekst. Potrebno je i definisati konfiguracionu klasu sa @ComponentScan kako bi
Spring znao gde da traži te klase. Takođe, moguće je kombinovati oba pristupa u složenijim
slučajevima.
Koraci koji se prate u ovom procesu su sledeći (slika 6.1):
• Korišćenjem anotacije @Component, označavaju se klase za koje Spring treba da doda
instancu u kontekst (npr. klasa Parrot).
• Korišćenjem anotacije @ComponentScan iznad konfiguracione klase, Spring se
usmerava gde da pronađe klase koje su označene.
32
Poglavlje 5 Dodavanje novih bean-ova u Spring kontekst
Slika 5.3.1 Korišćenje stereotipnih anotacija za dodavanje bean-ova u Spring kontekst Izvor: [1]
KORIŠĆENJE STEREOTIPNIH ANOTACIJA ZA DODAVANJE BEAN-OVA
U SPRING KONTEKST - IMPLEMENTACIJA
Instanca može biti dodata u Spring kontekst tako što se klasa anotira
stereotipnom anotacijom @Component.
Na primeru klase Parrot, instanca može biti dodata u Spring kontekst tako što se klasa
anotira stereotipnom anotacijom, npr. @Component. Sledeći listing prikazuje kako se koristi
anotacija @Component za klasu Parrot.
@Component
public class Parrot {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Ovaj kod još uvek neće raditi. Spring podrazumevano ne pretražuje klase koje su anotirane
stereotipnim anotacijama, tako da ako se kod ostavi u ovom obliku, Spring neće dodati bean
tipa Parrot u svoj kontekst. Da bi se Spring-u nagovestilo da treba da traži klase označene
stereotipnim anotacijama, koristi se anotacija@ComponentScan iznad konfiguracione klase.
Pomoću @ComponentScan anotacije, takođe se definiše gde Spring treba da traži te klase
– navode se paketi u kojima su definisane klase sa stereotipnim anotacijama. Sledeći listing
prikazuje kako se koristi anotacija @ComponentScan iznad konfiguracione klase projekta. U
ovom primeru, ime paketa je „main“.
Sledeći listing prikazuje kako se koristi anotacija @ComponentScan iznad konfiguracione
klase projekta. U ovom primeru, ime paketa je „main“.
33
Poglavlje 5 Dodavanje novih bean-ova u Spring kontekst
@Configuration
@ComponentScan(basePackages = "main")
public class ProjectConfig {}
Sada je Spring-u naznačeno sledeće:
• Koje klase treba da dodaju instancu u kontekst (Parrot)
• Gde da pronađe te klase (korišćenjem@ComponentScan)
Više nisu potrebne metode za definisanje bean-ova. Na prvi pogled, ovaj pristup deluje boljim
jer se isti rezultat postiže uz manje koda. Međutim, treba sačekati kraj poglavlja – biće
objašnjeno da su oba pristupa korisna u zavisnosti od situacije.
Glavna metoda se može nastaviti kako je prikazano u sledećem listingu, kako bi se potvrdilo
da Spring zaista kreira i dodaje bean u svoj kontekst.
public class Main {
public static void main(String[] args) {
var context = new
AnnotationConfigApplicationContext(ProjectConfig.class);
Parrot p = context.getBean(Parrot.class);
System.out.println(p);
System.out.println(p.getName());
}
}
Pokretanjem ove aplikacije može se uočiti da je Spring dodao instancu klase Parrot u svoj
kontekst, jer je prva ispisana vrednost podrazumevana string reprezentacija te instance.
Međutim, druga ispisana vrednost je null, jer nije dodeljeno nikakvo ime papagaju. Spring
kreira instancu klase, ali je i dalje odgovornost programera da izvrši eventualne izmene nad
tom instancom (npr. dodeljivanje imena).
POREĐENJE STEREOTIPNIH ANOTACIJA I @BEAN ANOTACIJE
Anotacija @Bean pruža potpunu kontrolu nad kreiranjem i
konfigurisanjem instance. Sa druge strane, stereotipne anotacije
omogućavaju jednostavnije dodavanje bean-ova bez dodatnog koda.
Postoje dva glavna pristupa za dodavanje bean-ova u Spring kontekst: korišćenje @Bean
anotacije i stereotipnih anotacija poput @Component. Anotacija @Bean pruža potpunu
kontrolu nad kreiranjem i konfigurisanjem instance. Omogućava dodavanje više instanci istog
tipa i može se koristiti za klase koje nisu deo aplikacije (npr. String, Integer). Nedostatak je
što zahteva dodatne metode, što povećava količinu koda.
Sa druge strane, stereotipne anotacije omogućavaju jednostavnije dodavanje bean-ova bez
dodatnog koda, ali se mogu koristiti samo za sopstvene klase i omogućavaju samo jednu
instancu po klasi. U praksi se najčešće koriste stereotipne anotacije, jer omogućavaju
dodavanje bean-ova uz manje pisanog koda.
34
Poglavlje 5 Dodavanje novih bean-ova u Spring kontekst
Anotacija @Bean se koristi kada bean nije moguće dodati na drugi način – na primer, kada je
u pitanju klasa iz biblioteke koju nije moguće izmeniti i u koju se ne može dodati stereotipna
anotacija.
Korišćenje anotacije @PostConstruct za upravljanje instancom nakon njenog
kreiranja
Kada se koristi stereotipna anotacija (npr. @Component), Spring kreira bean i dodaje ga u
kontekst, ali ne pruža punu kontrolu nad procesom kreiranja kao što je to slučaj sa @Bean.
Na primer, pomoću @Bean bilo je moguće odmah dodeliti ime instanci klase Parrot, dok kod
@Component to nije moguće direktno nakon konstruktora.
Ako je potrebno izvršiti određene instrukcije odmah nakon što Spring kreira bean, može
se koristiti anotacija @PostConstruct. Anotacija @PostConstruct, preuzeta iz Java EE,
koristi se za označavanje metode koju Spring treba da pozove odmah nakon izvršavanja
konstruktora. Metoda se definiše unutar klase komponente i anotira sa @PostConstruct.
Primer upotrebe u klasi Parrot:
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version>
</dependency>
Za Java verzije 11 i novije, potrebno je eksplicitno dodati zavisnost u pom.xml jer Java EE API
više nije deo JDK-a:
@Component
public class Parrot {
private String name;
@PostConstruct
public void init() {
this.name = "Kiki";
}
// Omitted code
}
Nakon ovoga, ako se ispiše ime papagaja, u konzoli će biti prikazano: Kiki. Takođe postoji
i anotacija @PreDestroy, koja označava metodu koju Spring poziva neposredno pre
zatvaranja konteksta. Iako može biti korisna (npr. za zatvaranje konekcija), preporučuje se
izbegavanje ove anotacije jer Spring ne garantuje uvek njeno izvršavanje, što može dovesti
do problema u radu aplikacije.
35
Poglavlje 5 Dodavanje novih bean-ova u Spring kontekst
5.3 Programski (manualno) dodavanje
bean-ova
PROGRAMSKI (MANUALNO) DODAVANJE BEAN-OVA U SPRING
KONTEKST
Spring od verzije 5 omogućava programsko, odnosno manualno
dodavanje bean-ova u kontekst, što daje veću fleksibilnost u poređenju
sa korišćenjem anotacija @Bean i stereotipnih anotacija.
Spring od verzije 5 omogućava programsko, odnosno manualno dodavanje bean-ova u
kontekst, što daje veću fleksibilnost u poređenju sa korišćenjem anotacija @Bean i
stereotipnih anotacija kao što je @Component. Ovaj pristup se koristi kada je potrebno na
specifičan način upravljati dodavanjem bean-ova — npr. uslovno, u zavisnosti od konfiguracije
aplikacije — što se ne može lako postići pomoću standardnih anotacija. Na primeru sa
papagajima: aplikacija učitava kolekciju objekata klase Parrot, gde su neki zeleni, a neki
narandžasti. Cilj je da se u Spring kontekst dodaju samo zeleni papagaji. Ovo se može
ostvariti programskim dodavanjem bean-ova.
Za to se koristi metoda registerBean() klase ApplicationContext, koja omogućava ručnu
registraciju beana u kontekstu. Metoda prima četiri parametra:
<T> void registerBean(
String beanName,
Class<T> beanClass,
Supplier<T> supplier,
BeanDefinitionCustomizer... customizers);
•
•
•
•
beanName – naziv beana (može biti null ako nije potreban).
beanClass – klasa beana, npr. Parrot.class.
supplier – implementacija funkcionalnog interfejsa Supplier koja vraća instancu objekta.
customizers – dodatne opcije za konfiguraciju beana, npr. označavanje kao primary.
Primer registracije:
public class Main {
public static void main(String[] args) {
var context =
new AnnotationConfigApplicationContext(
ProjectConfig.class);
Parrot x = new Parrot();
x.setName("Kiki");
Supplier < Parrot > parrotSupplier = () - > x;
context.registerBean("parrot1",
Parrot.class, parrotSupplier);
Parrot p = context.getBean(Parrot.class);
System.out.println(p.getName());
36
Poglavlje 5 Dodavanje novih bean-ova u Spring kontekst
}
}
Primer registracije:
context.registerBean("parrot1",
Parrot.class,
parrotSupplier,
bc -> bc.setPrimary(true));
U ovom pristupu nije potrebna ni posebna konfiguracija ni anotacije unutar same klase – klasa
Parrot ostaje običan POJO.
Programski način dodavanja bean-ova predstavlja snažan alat u specijalizovanim scenarijima
i značajan je korak ka razumevanju dubljih mehanizama rada Spring okvira. Ova veština je
osnova za dalje teme, kao što je rad sa bean-ovima iz konteksta, što se razmatra u sledećem
poglavlju.
37
Poglavlje 6
Pokazna vežba
PRIMER 1
Aplikacija simulira slanje poruka korisnicima kroz više kanala: e-mail,
SMS i push notifikacije.
Aplikacija simulira slanje poruka korisnicima kroz više kanala: e-mail, SMS i push notifikacije.
Svaki kanal koristi razlinitu metodu dodavanja bean-ova:
• EmailService koristi @Bean,
• SmsService koristi @Component,
• PushService se dodaje programski (manualno).
Izvršavanje
Svaka poruka se ispisuje u konzoli:
• Email sent: Dobrodošli!
• SMS sent: Vaš kod je 12345
• Push notification: Imate novu poruku!
Prvi korak je dodavanje zavisnosti u projekat kako je opisano na predavanjima kreiranjem
dependency tag-a. Poslednju verziju Spring konteksta možete naći na linku:
https://mvnrepository.com/artifact/org.springframework/spring-context.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>IT355-L01-primer1</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>20</maven.compiler.source>
<maven.compiler.target>20</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
38
Poglavlje 6 Pokazna vežba
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context
-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>6.2.5</version>
</dependency>
</dependencies>
</project>
Kada kreiraš ili otvoriš Maven projekat (pom.xml), IntelliJ: detektuje da koristiš Maven, i
prikazuje ti obaveštenje na vrhu sa dugmetom "Import Maven Projects" (ili automatski pita da
li da importuje).
Klikom na to "Import" dugme, IntelliJ: Prepoznaje strukturu Maven projekta, zatim preuzima
zavisnosti iz pom.xml (npr. Spring biblioteke). Nakon toga kreira target/ direktorijum i .iml
fajlove, generiše konfiguraciju projekta (source folders, test folders, JDK itd.). Na kraju
uključuje sve module u projekat.
Prikazuje se u žutom traku na vrhu editora kada otvoriš pom.xml fajl. Možeš ga naći i u
desnom panelu "Maven" → ikonica sa dva kružna strelice (��) → Reload All Maven Projects.
PRIMER 1 - NASTAVAK
Struktura projekta prolazi kroz 3 koraka.
KORAK 1:
Napravljene su tri klase koje simuliraju sve ove servise posebno.
EmailService – obična Java klasa:
package services;
public class EmailService {
public void send(String msg) {
System.out.println("Email sent: " + msg);
}
}
PushService – obična Java klasa
package services;
public class PushService {
public void send(String msg) {
System.out.println("Push notification: " + msg);
}
}
SmsService – klasa anotirana sa @Component
39
Poglavlje 6 Pokazna vežba
package services;
import org.springframework.stereotype.Component;
@Component
public class SmsService {
public void send(String msg) {
System.out.println("SMS sent: " + msg);
}
}
KORAK 2:
ProjectConfig – klasa konfiguracije. Ovde se:
• koristi @ComponentScan da bi Spring pronašao i instancirao SmsService
• koristi @Bean metoda da bi se registrovao EmailService
package config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import services.EmailService;
@Configuration
@ComponentScan(basePackages = "services")
public class ProjectConfig {
@Bean
public EmailService emailService() {
return new EmailService();
}
}
KORAK 3:
Glavna klasa – pokretanje aplikacije i dodavanje PushService
import config.ProjectConfig;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import services.EmailService;
import services.PushService;
import services.SmsService;
public class Main {
public static void main(String[] args) {
var context = new AnnotationConfigApplicationContext(ProjectConfig.class);
PushService push = new PushService();
context.registerBean("pushService", PushService.class, () -> push);
EmailService email = context.getBean(EmailService.class);
40
Poglavlje 6 Pokazna vežba
SmsService sms = context.getBean(SmsService.class);
PushService pushBean = context.getBean(PushService.class);
email.send("Dobrodošli!");
sms.send("Vaš kod je 12345");
pushBean.send("Imate novu poruku!");
}
}
Dodavanje bean-a u Spring kontekst se može postići na tri različita načina. Svaki pristup
ima svoje prednosti u zavisnosti od potreba projekta. @Component je najjednostavniji
kada radimo sa sopstvenim klasama. @Bean je odličan kada želimo preciznu kontrolu nad
instancom. Programatsko dodavanje ( registerBean) je fleksibilno i korisno u dinamičkim
scenarijima.
PRIMER 2
Simulirati trku dva automobila. U Spring kontekst se dodaju dve
različite instance iste klase Car — jedan pomoću @Bean, a drugi
programatski (manualno) pomoću registerBean().
Ovaj primer prikazuje kako da se u Spring kontekst dodaju dve različite instance iste klase
(Car) pomoću dva različita pristupa:
• statički – pomoću @Bean metode,
• dinamički – programatski pomoću registerBean().
Kroz simulaciju trke dva automobila, naučićemo kako:
• se upravlja bean-ovima istog tipa,
• se koriste nazivi bean-ova (bean name) da bi se razlikovali,
• se koristi Spring kontekst za ručno registrovanje objekata.
Pre svega, potrebno je definisati običnu POJO klasu koja predstavlja automobil. Ona sadrži
osnovne podatke: ime i brzinu, kao i metodu drive() koja simulira vožnju.
package primer2;
public class Car {
private String name;
private int speed;
public Car(String name, int speed) {
this.name = name;
this.speed = speed;
}
public void drive() {
System.out.println(name + " vozi brzinom " + speed + " km/h");
41
Poglavlje 6 Pokazna vežba
}
public int getSpeed() {
return speed;
}
public String getName() {
return name;
}
}
Klasa je potpuno nezavisna od Spring-a. Nema nikakvih anotacija (@Component), jer ćemo je
dodavati na drugačije načine u kontekst. Služi kao model automobila u trci.
Spring omogućava da se bean doda preko metode koja vraća instancu objekta i anotirana je
sa @Bean. Ova metoda se piše u konfiguracionoj klasi.
package primer2.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import primer2.Car;
@Configuration
@ComponentScan(basePackages = "primer2")
public class ProjectConfig {
@Bean(name = "redCar")
public Car redCar() {
return new Car("Crveni auto", 120);
}
}
Klasa ProjectConfig je anotirana sa @Configuration, što znači da je izvor bean definicija.
Metoda redCar() vraća objekat Car sa određenim imenom i brzinom. Bean se eksplicitno
imenuje kao "redCar".
U glavnoj klasi, možemo u trenutku pokretanja aplikacije ručno dodati drugi automobil u
kontekst pomoću registerBean().
Car blue = new Car("Plavi auto", 135);
context.registerBean("blueCar", Car.class, () -> blue);
PRIMER 2 - NASTAVAK
U glavnoj klasi pravimo kontekst, dodajemo bean programatski, i
upoređujemo performanse oba automobila.
42
Poglavlje 6 Pokazna vežba
U glavnoj klasi pravimo kontekst, dodajemo bean programatski, i upoređujemo performanse
oba automobila.
package primer2;
import primer2.config.ProjectConfig;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Main {
public static void main(String[] args) {
var context = new AnnotationConfigApplicationContext(ProjectConfig.class);
// Dodavanje drugog auta programatski
Car blue = new Car("Plavi auto", 135);
context.registerBean("blueCar", Car.class, () -> blue);
// Dohvati oba auta po imenu
Car redCar = (Car) context.getBean("redCar");
Car blueCar = (Car) context.getBean("blueCar");
System.out.println("Trka počinje!");
redCar.drive();
blueCar.drive();
// Odredi pobednika
String winner = redCar.getSpeed() > blueCar.getSpeed() ? redCar.getName() :
blueCar.getName();
System.out.println("Pobednik je: " + winner);
}
}
Objašnjenje:
•
•
•
•
•
Spring kontekst se inicijalizuje pomoću konfiguracione klase.
Prvi bean (redCar) je već registrovan pomoću @Bean.
Drugi bean (blueCar) se dodaje u runtime-u.
Oba beana se dohvataju po imenu jer su istog tipa (Car).
Na kraju se izvršava logika trke i određuje pobednik.
43
Poglavlje 7
Individualna vežba 1
ZADATAK ZA SAMOSTALNI RAD
Ove zadatke student treba da izradi samostalno.
ZADATAK 1: Biblioteka – registracija dve knjige
Napiši Spring aplikaciju u kojoj se registruju dve knjige (Book).
•
•
•
•
Klasa Book ima title i author kao polja.
Jedna knjiga se dodaje kao bean pomoću @Bean metode u konfiguraciji.
Druga knjiga se dodaje programatski pomoću registerBean() u Main klasi.
Nakon učitavanja konteksta, ispiši podatke o obe knjige.
Napomena: Obavezno koristi
getBean(String) za dohvat.
različita
imena
bean-ova
(book1,
book2)
i
koristi
ZADATAK 2: Muzicki plejer i pesme
Napraviti aplikaciju koja modeluje jednostavan muzički plejer.
•
•
•
•
Klasa Song sadrži title i duration.
Napraviti jednu pesmu pomoću @Component anotacije.
Dodati još jednu pesmu programatski u Main klasi.
Dodati klasu MusicPlayer preko @Bean metode, koja ispisuje sve dostupne pesme u
kontekstu.
Ispis u konzoli treba da bude:
Pesma: Never Gonna Give You Up (3:33)
Pesma: Africa (4:12)
ZADATAK 3: Galerija – slike različitim metodama
Modeluj aplikaciju za galeriju slika gde se učitavaju tri slike (Image).
•
•
•
•
•
Klasa Image ima name i resolution.
Jedna slika se dodaje pomoću @Bean metode.
Druga slika se anotira sa @Component.
Treća slika se dodaje programatski u Main klasi.
U Main klasi ispiši sve tri slike iz konteksta.
Možeš koristiti getBean(String) ili getBeansOfType(Image.class) da bi pronašao sve slike.
44
Poglavlje 8
Zaključak
ZAKLJUČAK
Lekcija je obradila osnovnu arhitekturu Spring okvira i pregled
unapređenja kroz revizije 4.x.
U lekciji detaljno je predstavljen značaj i osnove Spring okvira kao ključnog alata u
savremenom Java programiranju. Spring se pozicionira kao moćna i fleksibilna platforma
za razvoj aplikacija, koja omogućava bolju organizaciju koda, lakše održavanje, efikasnije
testiranje i jednostavniju integraciju sa drugim komponentama sistema. Kroz koncept
Inversion of Control (IoC), Spring omogućava automatizovano upravljanje objektima i
njihovim međusobnim zavisnostima, što značajno pojednostavljuje razvoj složenih sistema.
Istaknuto je da Spring omogućava razvoj aplikacija na osnovu običnih Java objekata (POJO),
čime se smanjuje kompleksnost i povećava čitljivost i fleksibilnost koda. Korišćenjem modula
poput Spring Core, Spring Data i Spring Boot, programeri dobijaju sveobuhvatan alat za
implementaciju širokog spektra funkcionalnosti – od osnovne poslovne logike, preko pristupa
podacima i bezbednosti, do razvoja REST servisa i testiranja.
Kroz praktične primere i realne scenarije, prikazano je kako Spring može da se koristi u
raznim tipovima aplikacija – od serverskih rešenja, preko desktop i mobilnih aplikacija, do
automatizovanih sistema za testiranje. Takođe je podvučeno da, iako je Spring izuzetno
moćan, nije uvek optimalan izbor, naročito kada je potrebna minimalna memorijska potrošnja
ili visoka prilagođenost bezbednosnim zahtevima. Lekcija ističe da razumevanje osnova
Spring konteksta i načina definisanja i upravljanja "bean"-ovima predstavlja prvi i ključni
korak ka uspešnom korišćenju celokupnog Spring ekosistema.
LITERATURA
Za pripremu lekcije korišćena je najnovija pisana i elektronska
literatura.
Za pripremu lekcije korišćena je literatura:
1. Spilca, L. (2021). Spring Start Here: Learn what you need and learn it well. Simon
and Schuster, poglavlje 1 i 2
2. Walls, C. (2022). Spring in action. Simon and Schuster.
45
Poglavlje 8 Zaključak
3. Deinum, M., Long, J., & Rubio, D. (2023). Spring 6 Recipes: A Problem-Solution
Approach to Spring Framework. Apress.
Dopunska literatura:
1.
http://www.javacodegeeks.com/tutorials/java-tutorials/enterprise-java-tutorials/springtutorials/
2. http://www.tutorialspoint.com/spring/
3. http://www.javatpoint.com/spring-tutorial
46
0
You can add this document to your study collection(s)
Sign in Available only to authorized usersYou can add this document to your saved list
Sign in Available only to authorized users(For complaints, use another form )