Annotations

Core Spring Framework Annotations

@Autowired

Το autowiring είναι ένα μέσο, όπου επιτρέπουμε στο Spring να ικανοποιήσει αυτόματα τις εξαρτήσεις ενός bean, βρίσκοντας άλλα beans στο application context, τα οποία ταιριάζουν στις ανάγκες του bean. Για να υποδείξουμε στο Spring, ότι πρέπει, να πραγματοποιηθεί autowiring, χρησιμοποιηούμε το annotation @Autowired είτε σε ένα field, είτε σε ένα κατασκευαστή.

@Configuration

Με το annotation @Configuration ορίζουμε, ότι η κλάση μας θα είναι configuration class και ότι θα περιέχει λεπτομέρειες, σχετικά με τα αντικείμενα, τα οποία θα δημιουργηθούν στο Spring application context.

                    
                        @Configuration
		                public class AmazonS3Configuration{

	                    }
                    
                

@Bean

Το annotation @Bean χρησιμοποείται σε επίπεδο μεθόδου και υποδεικνύει στο Spring, ότι η μέθοδος αυτή θα επιστρέψει ένα αντικείμενο, το οποίο θα πρέπει, να εγγραφεί ως bean στο Spring application Context με το όνομα awsS3AudioBucket.

                    
                        @Configuration
		                public class AmazonS3Configuration{

                        @Bean(name = "awsS3AudioBucket")
                        public String  getAWSS3AudioBucket() {
                        return awsS3AudioBucket;
                          }

	                    }
                    
                

@ComponentScan

Το annotation @ComponentScan επιτρέπει στο Spring, να αναζητάει annotated components.

Spring Framework Stereotype Annotations

@Component

Χρησιμοποιούμε το annotation @Component, για να δηλώσουμε ότι η κλάση είναι ένα Spring component. Το annotation σημειώνει την κλάση ως ένα bean, ώστε ο μηχανισμός ανίχνευσης components του Spring, να τα προσθέσει στο application context.

                                            
                        @Component
                        public class EmailServiceImp implements  EmailService{

                        }
                    
                

@Repository

Το annotation είναι μια πιο ειδική περίπτωση του annotation @Component και χρησιμοποείται για κλάσεις, που έχουν πρόσβαση στη βάση δεδομένων.

                                            
                        @Repository
                        public interface ProductRepository extends  JpaRepository{

                        }
                    
                

@Service

Το annotation είναι μια πιο ειδική περίπτωση του annotation @Component και χρησιμοποείται για κλάσεις, που ανήκουν στο service layer.

                                            
                        @Service("productService")
                        @Transactional
                        public class ProductServiceImpl  implements ProductService{

                        }
                    
                

@Controller

Το annotation είναι μια πιο ειδική περίπτωση του annotation @Component, σημειώνει την κλάση ως Spring Web MVC Controller και εισάγεται στο Spring IoC Container.

                                            
                        @Controller
                        public class RoutesController {

                        }
                    
                

Spring Boot Annotations

@SpringBootApplication

Το annotation @SpringBootApplication προσθέτει τα annotations @Configuration, @EnableAutoConfiguration και @ComponentScan. χρησιμοποείται στην κύρια κλάση της εφαρμογής και πρέπει, να βρίσκεται στο base package. Για παράδειγμα, αν η κλάση με το annotation τοποθετηθεί στο package springeshop, τότε το spring θα κάνει component scan μόνο στα subpackages, όπως springeshop.configuration και springeshop.model .

                                            
                        @EnableAsync
                        @SpringBootApplication(scanBasePackages={"springeshop"})
                        public class SpringEshopApplication {

                        }
                    
                

@EnableAutoConfiguration

Το annotation @EnableAutoConfiguration τοποθετείται στην κύρια κλάση της εφαρμογής και ενεργοποιεί τον μηχανισμό auto-configuration του Spring. Ο μηχανισμός αυτός προσπαθεί, να ρυθμίσει αυτόματα την εφαρμογή, βασισμένος στα jar dependencies ,που έχουμε προσθέσει στο classpath.

Spring MVC and REST Annotations

@RestController

Το annotation αυτό χρησιμοποείται σε επίπεδο κλάσης. Σημειώνει την κλάση ως έναν controller, ο οποίος θα επιστρέφει ένα domain oject αντί για ένα view. Δηλαδή δεν στέλνεται html ως απάντηση, αλλά ένα domain object σε μορφή, την οποία καταλαβαίνει ο καταναλωτής όπως JSON.

                                            
                        @RestController
                        @RequestMapping("/api")
                        public class CategoryApiController {

                        }
                    
                

@RequestMapping

Το annotation αυτό χρησιμοποείται σε επίπεδο κλάσης και μεθόδου. Αντιστοιχίζει ένα αίτημα HTTP σε μια συγκεκριμένη μέθοδο, η οποία θα το χειριστεί. Όταν το annotation χρησιμοποείται σε επίπεδο κλάσης, ορίζει το βασικό URL, για το οποίο θα χρησιμοποιηθεί ο controller. Η κάθε μέθοδος θα αντιστοιχίζεται σε διαφορετικό URL. Η παράμετρος method δηλώνει τι τύπου θα είναι το HTTP request, το οποίο θα χειριστεί η μέθοδος. Για παράδειγμα, όταν πραγματοποιηθεί HTTP GET αίτημα στο URL http://localhost:8080/api/deals, θα εκτελεστεί η μέθοδος getDeals().

                                            
                        
                        @RestController
                        @RequestMapping("/api")
                        public class DealApiController {

                              @Autowiredprivate DealService dealService;

                              @Autowiredprivate DealImageService dealImageService;
                            
                              public static final Logger logger = LoggerFactory.getLogger(DealApiController.class);

                              @RequestMapping( value = "/deals", method = RequestMethod.GET)
	                          public ResponseEntity<?> getDeals(){

                                    List deals = dealService.findAllDeals();
		
                                    if(deals.isEmpty()){
                                      return new ResponseEntity<>(HttpStatus.NO_CONTENT);
                                    }

                                    for(Deal deal : deals){
                                     DealImage dealImage = dealImageService.findByDeal(deal);
                                     deal.setImageUrl(dealImage.getUrl());
                                    }

                                    return new ResponseEntity<List<Deal>>(deals, HttpStatus.OK);
                              }
                        }
                    
                

@PathVariable

Το annotation χρησιμοποείται στις παραμέτρους μεθόδου. Χειρίζεται δυναμικές αλλαγές στο URL, όπου ένα κομμάτι του URL λειτουργεί ως παράμετρος. Για παράδειγμα, η παρακάτω μέθοδος getProductByName() θέλουμε, να επιστρέφει το σωστό προιόν, ανάλογα με το όνομα του προιόντος στο url. Όταν ο client θέλει το προιόν με όνομα apivita-shampoo-dry-dandruff-250ml, κάνει ένα HTTP GET request στο url http://localhost:8080/api/products/apivita-shampoo-dry-dandruff-250ml και η παράμετρος name της μεθόδου παίρνει την τιμή "apivita-shampoo-dry-dandruff-250ml".

                                            
                        @RequestMapping( value = "/products/{name}", method = RequestMethod.GET)
                        public ResponseEntity<?> getProductByName(@PathVariable("name") String name) {
                            
                               logger.info("Fetching Product with name {}", name);
                               Product product = productService.findByName(name);

                               if(product == null){
                                     logger.error("Product with name {} not found.", name);
                                     return new ResponseEntity<>(new ErrorMessage("Product with name {}" + name + " not found"), HttpStatus.NOT_FOUND);
                               }

                               ProductImage productImage = productImageService.findByProductId(product.getId());
                               product.setSmallImageUrl(productImage.getSmallImageurl());
                               product.setLargeImageUrl(productImage.getLargeImageurl());
                               product.setVerySmallImageUrl(productImage.getVerySmallImageurl());

                               int productQuantity = inventoryService.findProductQuantity(product.getId());
                               product.setQuantity(productQuantity);

                               return new ResponseEntity<Product>(product, HttpStatus.OK);
                        }
                    
                

@RequestParam

Το annotation χρησιμοποείται στις παραμέτρους μεθόδου. Αντιστοιχίζει τις παραμέτρους που στέλνει ο client, συνήθως με GET request, με παραμέτρους της μεθόδου , η οποία θα χειριστεί το αίτημα. Όταν o client θέλει τα brands της κατηγορίας shampoos, κάνει ένα GET HTTP request στο URL http://localhost:8080/api/brands?category=shampoos και η παράμετρος category της μεθόδου getCategoryBrands() παίρνει την τιμή "shampoos".

                    
                            @RequestMapping( value = "/brands", method = RequestMethod.GET)
                            public ResponseEntity<?> getCategoryBrands(@RequestParam(value ="category", required = false String category) {

                                Category requestedCategory = categoryService.findByName(getCorrectCategoryName(category));

                               if(requestedCategory == null){
                                  return new ResponseEntity<>(new ErrorMessage("Category does not exist"), HttpStatus.BAD_REQUEST);
                               }

                                List<Brand> brands = productService.findCategoryBrands(requestedCategory.getId());

                               if(brands.isEmpty()){
                                  return new ResponseEntity<>(HttpStatus.NO_CONTENT);
                               }

                               brands.sort((Brand brand1, Brand brand2) -> brand1.getName().compareTo(brand2.getName()));

                               return new ResponseEntity<List<Brand>>(brands, HttpStatus.OK);
                            }
                    
                

@RequestBody

Το annotation χρησιμοποείται στις παραμέτρους μεθόδου. Αντιστοιχίζει την τιμή του HTTP request body με την παράμετρο της μεθόδου, η οποία θα χειριστεί το αίτημα. Όταν o client θέλει να κάνει register, κάνει ένα HTTP POST request στο URL http://localhost:8080/api/register και η παράμετρος user της μεθόδου registerUser() παίρνει την τιμή του request body.

                    
                            @RequestMapping( value = "/register", method = RequestMethod.POST)
                            public ResponseEntity<?> registerUser(@Valid @RequestBody User user) {
                                 logger.info("Register user : {}", user);

                               if(userService.doesUserExist(user)){
                                  return new ResponseEntity<>(new ErrorMessage("A user with username " + user.getUsername() + "already exists"), HttpStatus.CONFLICT);
                               }

                               if(userService.doesEmailExist(user)){
                                  return new ResponseEntity<>(new ErrorMessage("Unable to create. A user with email " + user.getEmail() + "already exists"), HttpStatus.CONFLICT);
                               }

                                 user.setPassword(passwordEncoder.encode(user.getPassword()));
                                 user.setIs_active(true);

                               if(userService.addUserAndIsSuccess(user)){
                                 Authority authority = new Authority();
                                 authority.setUser(user);
                                 authority.setRole("ROLE_USER");
                                if(authorityService.saveAuthorityAndIsSuccess(authority)){
                                  return new ResponseEntity<>(user, HttpStatus.CONFLICT);
                                }
                               }

                               return newResponseEntity<>(user, HttpStatus.INTERNAL_SERVER_ERROR);
                            }
                    
                

@RequestPart

Το annotation χρησιμοποείται στις παραμέτρους μεθόδου. Μπορεί να χρησιμοποιηθεί αντί για το annotation @RequestParam και να πάρουμε το περιεχόμενο μιας φωτογραφίας.

                    
                            @RequestMapping( value = "/products", method = RequestMethod.POST)
                            public ResponseEntity<?> createProduct(@Valid @RequestPart(value = "product") Product product, 
                                           @RequestPart (value = "smallImage") MultipartFile smallImage, @RequestPart(value = "largeImage") MultipartFile largeImage, 
                                           @RequestPart (value = "verySmallImage") MultipartFile verySmallImage) throws InterruptedException, ExecutionException {
                            
                    
                

JPA Annotations

@Entity

Ορίζει ότι η αυτή η κλάση, είναι ένα entity.

                
                        @Entity 
                        @Table(name = "brands")
                        public class Brand  {

                        } 
                
            
@Table(name = "tableName")

Ορίζει τον πίνακα της βάσης δεδομένων, με τον οποίο θα αντιστοιχίστει το entity.

                
                        @Entity 
                        @Table(name = "brands")
                        public class Brand  {

                        } 
                
            
@Column(name = "columnName")

Ορίζει την στήλη του πίνακα, με την οποία θα αντιστοιχίστει το πεδίο του entity.

                
                        @Column(name = "quantity")
                        private int quantity;
                
            
@Transient

Ορίζει ότι αυτό το πεδίο δεν θα αποθηκευτεί στον πίνακα της βάσης.

                
                        @Transient
                        private int quantity;
                
            
@Id

Ορίζει το πρωτεύον κλειδί του πίνακα.

                

                        @Id
                        @GeneratedValue(strategy = GenerationType.IDENTITY)
                        @Column(name = "id")
                        private int id;
                
            
@GeneratedValue(strategy = STRATEGY)

Ορίζει την στρατηγική παραγωγής τιμών του πρωτεύοντος κλειδιού.

                

                        @Id
                        @GeneratedValue(strategy = GenerationType.IDENTITY)
                        @Column(name = "id")
                        private int id;
                
            
@NotNull

Ορίζει το συγκεκριμένο πεδίο δεν πρέπει, να είναι null.

                
                           @Column(name = "name")
                           @NotNull(message = "Please provide category name")
                           private String name;
                
            
@OneToOne, @OneToMany, @ManyToOne, @ManyToMany

Xρησιμοποείται, για να δηλώσουμε την πολλαπλότητα της σχέσης των entities.

                
                           @ManyToOne (optional = false)
                           @JoinColumn(name = "category_id")
                           @NotNull 
                           private Category category;
                        } 
                
            
@JoinColumn

Ορίζει τη στήλη, ως τη join στήλη για τη συσχέτιση των entities.

                
                           @ManyToOne (optional = false)
                           @JoinColumn(name = "category_id")
                           @NotNull 
                           private Category category;
                        } 
                
            
@Embeddable

Χρησιμοποείται σε μια κλάση, για να αναπαραστήσει την κατάσταση ενός entity, αλλά δεν θα αποθηκευτεί στη βάση δεδομένων.

                
                           @Embeddable 
                           public class OrderProductPrimaryKey implements Serializable  {

                           } 
                
            
@EmbeddedId

Χρησιμοποείται σε ένα πεδίο, για να δηλώσει ότι είναι σύνθετο πρωτεύον κλειδί και embeddable κλάση.

                
                           @EmbeddedId
                           private OrderProductPrimaryKey id;
                        } 
                
            
@MapsId

Χρησιμοποείται σε attributes συσχέτισης @ManyToOne ή @OneToOne, το οποίο παρέχει την αντιστοίχιση για ένα attribute μέσα σε ένα @EmbeddedId πρωτεύον κλειδί.

                
                           @OneToOne (fetch = FetchType.LAZY)
                           @MapsId("orderId")
                           private Order order;
                        } 
                
            

JSR-303 Annotations

@Valid

Πραγματοποιεί validation στο μοντέλο, αφού πάρει τιμή.

@Transactional

Task Execution Annotations

@Async

Το χρησιμοποιούμε, όταν θέλουμε μια μέθοδος να εκτελεστεί σε ξεχωριστό νήμα.

@EnableAsync

Ενεργοποιεί τη λειτουργία εκτέλεσης ασύγχρονων μεθόδων του Spring.