No to zaczynamy! Dzisiejszy niezbędnik odpowie na najważniejsze pytania związane z adnotacjami.
#Niezbędnik Juniora
Niezbędnik juniora to seria, która ma pomóc Ci w uporządkowaniu i sprawdzeniu wiedzy np. przed rozmową kwalifikacyjną. Staramy się w prosty sposób odpowiedzieć na potencjalne pytania, a także dać Ci odpowiednie odnośniki do bardziej szczegółowych artykułów. W cyklu postaramy się przejść przez najważniejsze zagadnienia związane z Javą, Springiem i aplikacjami webowymi, podstawami pracy z bazami danych czy repozytoriami na git. Nie będą to jednak pełne lekcje, a raczej pigułkowe opracowania w sam raz na uporządkowanie wiedzy.
Każdy odcinek składa się z pytań, na które postaramy się odpowiedzieć, a czasem kilku zadań dla Ciebie związanych z zagadnieniem. Zachęcamy do zadawania dodatkowych pytań w komentarzach postaramy się na nie odpowiedzieć.
#Adnotacje
Co to jest adnotacja?
Za dokumentacją Javy: Adnotacje to metadane (a więc dane o danych — w naszym przypadku dane o kodzie), która dostarczają nam takich informacji o programie, które nie są częścią tego programu (same w sobie). Adnotacje nie mają bezpośredniego wpływu na kod, który nimi oznaczamy.
Są one używane np. przez framework przy uruchamianiu naszego programu by w odpowiedni sposób interpretować nasz kod.
Działanie adnotacji opiera się na mechanizmie refleksji, czyli procesowi, który pozwala m.in. na zdobywanie informacji o klasach w trakcie wykonania programu.
Jak wyglądają adnotacje w Javie?
Przykładowy kod z adnotacjami znajdziecie poniżej (jeśli widzieliście nasze lekcje Javy na pewno bez problemu je wskażecie).
@Controller
public class LoginController
{
@RequestMapping( value = "/login", method = RequestMethod.GET )
public String login()
{
return "login";
}
}
Adnotacje zaczynają się od @, która wskazuje kompilatorowi — że to adnotacja.
Adnotacje mogą zawierać w sobie dodatkowe informacje np. (name=„books”), które podajemy w nawiasie, na zasadzie nazwa=wartość, a jeśli mamy ich kilka, to możemy je podać po przecinkach. Jeśli podamy samą wartość to Java uzna, że chodziło nam o pole o nazwie value.
Java 8 wspiera umieszczanie adnotacji „wszędzie”(tj. nad klasami, metodami, nad polami oraz przed argumentami metod). Poniżej przykładowe umieszczenia adnotacji.
@NotNull String name;
List<@NotNull String> names;
class UnmodifiableList implements @Readonly List<@Readonly T> {...}
email = (@Email String) input;
new @Information MyObject();
void doSomething() throws @ImportantForMe MyException { ... }
Jak działają adnotacje w Springu?
W najprostszym rozumieniu adnotacje to wskazówki dla Springa w jaki sposób ma traktować poszczególne metody, klasy, pola i dzięki temu jest w stanie samodzielnie tworzyć beany (czyli obiekty, którymi zarządza — więcej o beanach poczytasz w naszej lekcji), wstrzykiwać je (czyli to, co robi @Autowired), weryfikować zabezpieczenia (@Secured, @PreAuthorize, @PostAuthorize).
Adnotacje które dodajemy przed klasę nazywamy w Springu stereotypami i są one swego rodzaju “flagą”, która mówi Springowi, że obiekt danej kasy ma być zarządzany przez niego jako bean, a poszczególne typy sterepotypów mogę mieć też specjalne znaczenie dla Springa.
Wyrózniamy cztery podstawowe stereotypy:
- @Component,
- @Service
- @Repository
- @Controller
Jaka jest różnica pomiędzy @Component, @Service, @Repository, @Controller?
@Component jest podstawowym stereotypem dla każdego z komponentów, którymi ma zarządzać Spring. Adnotacja ta jest równoważna z <bean>.Każdy inny stereotyp dziedziczy własnie po @Component.
Oznacza to, że @Service, @Repository, @Controller to tak naprawdę adnotacja @Component z dodatkowymi informacjami. I tak:
@Service — wskazuje serwis w warstwie logiki biznesowej
@Repository — wskazuje DAO w warstwie przechowywania danych
@Controller — wskazuje kontroler w warstwie prezentacji
Dodatkowo, @Repository ze Spring-data tworzy dynamicznie klasę (bo ta adnotacja jest nad interfejsem), która obsługuje bazę danych wykonując zapytania, które generuje na podstawie nazw metod tego interfejsu. Powoduje też, że wyjątki związane z bazą danych są zamieniane na Springowe DataAccessExceptions.
Jaka jest różnica pomiędzy @Autowired, @Inject, @Resouces?
Wszystkie te adnotacje służą do wstrzykiwania obiektów. Pierwszą różnicą między nimi jest ich pochodzenie:
- @Resource – zdefiniowany w javax.annotation, który jest pakietem Javy
- @Inject – zdefiniowany w javax.inject package, który jest pakietem Java
- @Autowired – zdefiniowany w pakiecie org.springframework.bean.factory, który jest częścią Spring framework.
Spring wprowadził obsługę adnotacje @Resouce i @Inject by umożliwić pracę z aplikacjami Java EE.
@Autowired i @Inject działają dokładnie tak samo.
Istnieje dyskretna różnica pomiędzy działaniem @Autowired(@Inject) i @Resource, a mianowicie różnia się one kolejnościa dobierania pasujących obiektów (po szczegóły odsyłam do materiałów dodatkowych, bo to już trochę niuans [5]).
Jaka jest zależność pomiędzy @Autowired oraz xmlem?
Możemy stowrzyć plik bean.xml, w którym będziemy ręcznie tworzyć beany. Przykładowa deklaracja beana znajduje się poniżej.
<bean id="teslaCat" class="teslaCat">
<property name="food" ref="food" />
</bean>
Co jest równoważne z umieszczeniem następujących adnotacji:
@Component
public class TeslaCat{
@Autowired
private Food food;
@Required
public void set Food(Food food) {
this.food = food;
}
Jakie jeszcze adnotacje możesz kojarzyć?
@Override — używana do oznaczania implementacji metod z interfejsów
@Valid — użyta w kontrolerze przy atrybucie metody powoduje, że obiekt ten jest traktowany jako formularz i uruchamiana jest jego walidacja (np. na podstawie poniższych adnotacji). Kolejny argument metody po tym musi być typu BindingResult — tam Spring umieści informacje o problemach
@NotNull — pole musi mieć wartość(nie może być nullem)
@NotBlank — pole nie może być czyste (np. wypełnione tylk białymi znakami)
@NotEmpty — pole nie może być puste
@Email — pole zawiera poprawny (od strony składni, niekoniecznie istniejący!) adres email
@RequestMapping — mapuje adres URL i/lub metodę HTTP na metodę kontrolera
@ResponseBody — Spring stara się przekształcić zwrócone wartości w odpowiedź http (np. konwertując obiekt na format JSON lub XML)
@RequestBody, Spring stara się przekształcić treść przychodzącego żądania w obiekt, np. kiedy chcemy otrzymać dane JSON i automatycznie je zamienić na obiekt.
@RequestParam — pozwala pobrać wartość parametru przekazywanego w adresie url np. “?userId=5”, do zmiennej
@PathVariable — obsługuje zmienną przekazaną w postaci fragmentu adresu url np. user/5 (user/{userId})
@Required — sprawdza, czy dane pole zostało ustawione (czy Spring wstrzyknął mu wartość) podczas uruchamiania
@Transactional — Pozwala zgrupować wiele czynności w ramach jednej transakcji bazy danych. Dzięki temu w przypadku niepowodzenia jednej z nich, pozostałe zostaną wycofane.
@Entity — Adnotacja, która mówi o tym, że ta klasa jest zarządzana przez JPA i odpowiada tabeli w bazie danych
@Table — Dzięki tej adnotacji możemy określić dodatkowe parametry związane z tabelą bazy danych, którą ta klasa reprezentuje. Możemy określić np. nazwę.
@Column — Analogicznie do @Table, ale pozwala nam określać atrybuty kolumn w tabeli w bazie danych, np. ich typ, długość, nazwę.
Materiały dodatkowe / dokumentacja
- Kurs Oracla — adnotacje (EN)
- Kurs Vogella (EN)
- Adnotacje w Spring (EN)
- Ściąga z adnotacji w Springu (EN)
- Różnice między @Autowired, @Inject, @Resouces (EN)
Jeśli uważasz powyższą lekcję za przydatną, mamy małą prośbę: polub nasz fanpage. Dzięki temu będziesz zawsze na bieżąco z nowymi treściami na blogu ( i oczywiście, z nowymi częściami kursu Javy). Dzięki!