Stereotypy

Spring posiada zestaw kilku specjalnych adnotacji, które określają specyficzne role dla klas w ramach całej architektury. Nazywami je stereotypami. Opisane nimi klasy mają realizować konkretnie przypisane do nich zadania i nic poza tym.

Lista stereotypów

  • @Component
    Podstawowy stereotyp, który stanowi bazę dla wszystkich innych adnotacji tego typu. Często wykorzystujemy taką adnotację gdy chcemy stworzyć wyspecjalizowaną klasę narzędziową lub zwykłą klasę pomocniczą, np.:
    @Component
    public class MD5Encoder {
    
        private static final Logger LOG = LoggerFactory.getLogger(MD5Encoder.class);
    
        private static final String ALGORITHM = "MD5";
        
        private static final int HEX_BASE = 16;
    
        public String getMD5Hash(String password) {
    
            String md5Hash = null;
            if (password != null) {
                ...
            }
    
            return md5Hash;
        }
    }
    
  • @Controller
    Adnotacja "mówi" Springowi, że opisana nią klasa obsługuje przychodzące żądania HTTP. Po otrzymaniu żądania uruchamiana jest metoda, której mapowanie zostało dopasowane do ścieżki określonej w wysłanym żądaniu (szczegóły wyboru metod przedstawiamy w rozdziale Spring MVC - Mapowanie żądań HTTP (Request Mapping)). Na koniec metoda kontrolera zwraca obiekt odpowiedzi http (może jednak zwracać też void):
    @Controller
    public class ItemController {
    
        private ItemService itemService; 
    
        @Autowired
        public ItemController(ItemService itemService) {
            this.itemService = itemService;
        }
    
    
        @GetMapping("/dtColumns")
        public ResponseEntity<DTColumnsResponseDTO> getDTColumns() throws Exception {
        
            List<DTColumn> columns = itemService.getDTColumns();
            DTColumnsResponseDTO dtColumnsResponseDTO = new DTColumnsResponseDTO(columns);
            
            return new ResponseEntity<DTColumnsResponseDTO>(dtColumnsResponseDTO, HttpStatus.OK);
        }
    }
    
    W tym miejscu wspomnijmy jeszcze o jednej adnotacji, która co prawda nie należy do pakietu stereotypów Springa, ale jest bardzo często używana w kontekście mapowań rozszerzając możliwości adnotacji @Controller. Mowa tutaj o adnotacji @RestController. Stosując tą adnotację odpowiedzi będą automatycznie konwertowane do formatu JSON, co w wielu przypadkach będzie istotne, np. gdy zewnętrzna usługa oczekuje od nas danych właśnie w tym formacie:
    @RestController
    public class ItemController {
    
        private ItemService itemService; 
    
        ...
    }
    
    Więcej o adnotacji @RestController piszemy podczas opisu adnotacji @ResponseBody, w rozdziale : Spring MVC - Metody obsługi żądań HTTP (Handler Methods).
  • @Service
    Adnotacja przeznaczona jest dla klas, których zadaniem jest przetwarzanie logiki biznesowej. Innymi słowy używamy jej po to by oznaczyć główne miejsce przetwarzania danych za pomocą konkretnych algorytmów:
    @Service
    public class ItemServiceImpl implements ItemService {
    
        ...
    
        @Override
        public List<ItemResponseDTO> searchDTRecords(SearchRequestDTO searchRequestDTO)
                throws Exception {
        
            Sort sort = new Sort(Direction.valueOf(
            searchRequestDTO.getOrder().get(0).getDir().toUpperCase()),
                                                        getSortColumn(searchRequestDTO));
            Pageable pageable = new PageRequest(
            searchRequestDTO.getStart() / searchRequestDTO.getLength(),
                                                     searchRequestDTO.getLength(), sort);
        
            ...
        
            return appaItemsDtos;
        }
    }
    
  • @Repository
    Adnotacja oznacza, że dana klasa zarządza bezpośrednio warstwą utrwalania danych, definując przy tym całkiem spory zestaw predefiniowanych metod pomocniczych. Traktuje ona wszystkie obiekty danego typu jako zbiór danych i podchodzi do nich w podobny sposób jak się podchodzi do kolekcji (z jej metodami dodawania, usuwania i modyfikacji), dodając jedynie bardziej zaawansowane możliwości wyszukiwania. Pojęcie Repository zostało wprowadzone już w 2003 roku przez Erica Evansa w książce Domain-Driven Design: Tackling Complexity in the Heart of Software.
    Uwaga
    W przypadku gdy używamy interfejsu JPARepository nie musimy używać tej adnotacji. Wystarczy utworzyć własny interfejs rozszerzający interfejs JPARepository. W ramach takiego interfejsu możemy definiować własne zapytania (custom query), a nawet dokładać metody operujące na natywnych zapytaniach SQL (native query). O tych sposobach piszemy w rozdziałach: Spring Data JPA - Zapytania własne (Custom Queries) oraz Spring Data JPA - Zapytania natywne (Native Queries).
    public interface UserRepository extends JpaRepository<User, Long> {
    
        User findByEmailAndPassword(String email, String password);
    
        User findByEmail(String email);
    }
    
  • @Indexed
    Adnotacja została wprowadzona w Springu 5 i jest alternatywą dla skanowania ścieżek klas w celu wyszukiwania komponentów (classpath scanning). Skanowanie odbywa się na etapie kompilacji, co może się przyczynić do przyspieszenia startu dużych aplikacji biznesowych (poprzez rezygnację ze skanowania podczas uruchamiania). Aby skorzystać z tej funkcjonalności należy dodać do projektu zależność, która wygeneruje nam plik z listą komponentów:
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-indexer</artifactId>
            <version>${indexer.version}</version>
            <optional>true</optional>
        </dependency>
    </dependencies>
    
Nasza rekomendacja
Programując aplikacje webowe zalecamy tworzenie struktury opartej o łańcuch powiązanych obiektów, podobnie jak na poniższym przykładzie:
  1. ItemController - klasa z adnotacją @Controller
  2. ItemService - klasa z adnotacją @Service, wstrzyknięta do ItemController
  3. ItemRepository - interfejs rozszerzający JPARepository, wstrzyknięty do ItemService
W takiej sytuacji najpierw odpowiednia metoda kontrolera (wybrana na podstawie zdefiniowanego mapowania) przejmie żądanie. Następnie uruchomi ona metodę serwisu odpowiedzialną za przetworzenie danych, która to metoda wywoła odpowiednią metodę repozytorium (pobierającą, bądź utrwalającą dane w bazie).
Używamy w StartAPPa


Wszystkie moduły aplikacji używają adnotacji @RestController, @Service oraz @Component . Powyższe przykłady pochodzą z kodu źródłowego kursu Tabela Zaawansowana oraz Logowanie & Reset . Nie używamy adnotacji @Repository, gdyż tak jak piszemy wyżej wystarczy użyć interfejsu JPARepository.
W tej strefie znajdziesz wszystko co niezbędne, aby komfortowo uczyć się Springa. Doskonale opisany kod nie zawiera zbędnych komplikacji, tylko samą esencję w postaci praktycznych przykładów. Tutaj odnajdziesz wszystko co jest istotne w danym temacie. Otrzymujesz pakiet złożony z kilku projektów wraz z obszernym wytłumaczeniem kodu.
Linki
https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/stereotype/package-summary.html
https://www.javacodegeeks.com/2017/11/difference-component-service-controller-repository-spring.html

Stale się rozwijamy, a więc bądź na bieżąco!
Na ten adres będziemy przesyłać informacje o ważniejszych aktualizacjach, a także o nowych materiałach pojawiających się na stronie.
Polub nas na Facebooku:
Nasi partnerzy:
Javappa to również profesjonalne usługi programistyczne oparte o technologie JAVA. Jeśli chesz nawiązać z nami kontakt w celu uzyskania doradztwa bądź stworzenia aplikacji webowej powinieneś poznać nasze doświadczenia.
Kliknij O nas .