Bước tiến của Spring!

Kể từ Java 1.6 trở đi, các tính năng liên quan đến annotation đã được phát triển hoàn thiện, nhưng cũng phải rất lâu các kỹ sư của Spring mới nhận ra được sức mạnh của annotation (có lẽ là khi #Struts2 ra đời), và ở thời điểm hiện tại, nếu bạn vẫn bị tra tấn bởi việc cấu hình bean qua file #xml thì hãy nghĩ cách chuyển đổi sang annotation đi nhé, bạn sẽ có thêm thời gian để tận hưởng cuộc sống tươi đẹp này.

Các annotation nổi bật

Giả định rằng chúng ta có 3 gói:

  1. com.example.spring.boot (root package)
  2. com.example.spring.boot.repository
  3. com.example.spring.boot.service

Và 1 lớp:

public class SpringBootExample

Vậy Spring có nhứng #annotation nào chúng ta cần chú ý? (spring boot bản 2.4.4 mọi người nhé)

  1. @SpringBootApplication: nó là annotation wrap lại các annotations: @EnableAutoConfiguration, @ComponentScan @Configuration, chúng ta thường sử dụng ở lớp có hàm main, và lớp có hàm main thường được đặt ở root package
  2. @EnableAutoConfiguration: Cho phép spring tìm kiếm các bean thông qua spring-boot-autoconfig mà mình đã nói ở bài trước
  3. @Configuration: Chỉ định lớp được annotation là lớp chuyên dành cho việc cấu hình để tạo bean
  4. @ComponentScan: Chỉ định các gói cơ sở hoặc các lớp cơ sở để Spring có thể scan được các bean. Ví dụ bạn chỉ định package com.example.spring.boot (hay lớp SpringBootExample) thì tất cả các package con của nó cũng sẽ được scan (hãy cẩn thận nhé, vì sẽ có lúc bạn không mong muốn vậy)
  5. @PropertySource: Dùng để chỉ định các file properties sẽ được đọc và đưa vào ApplicationContext
  6. @ConfigurationProperties: Chỉ định lớp sẽ được map với các properties có prefix, ví dụ @ConfigurationProperties(prefix="db")
  7. @Component: Lớp được annotation sẽ là bean, được khởi tạo và đưa vào quản lý bởi ApplicationContext
  8. @Service: Cũng tương tự như @Component nhưng bạn nên sử dụng với các lớp service của bạn để tránh nhầm lẫn
  9. @Repository: Được dùng nhiều trong spring-data, để nhận diện các lớp tương tác với database hay cache từ đó có cách khởi tạo riêng biệt để đưa vào ApplicationContext
  10. @Controller: Được dùng cho các lớp tầng controller, dùng để handle request của người dùng và trả lại response!
  11. @Bean: Chỉ định hàm sẽ được gọi bởi Spring và kết quả sẽ là 1 bean được lưu vào ApplicationContext
  12. @Value: Dùng để map 1 field với 1 property trong ApplicationContext
  13. @Autowired: Dùng để chỉ định thuộc tính hoặc phương thức sẽ được inject bean vào từ ApplicationContext, nếu bạn không muốn sử dụng @Autowired, bạn có thể sử dụng hàm tạo, spring cũng sẽ tự inject bean cho bạn.

Đây chỉ 1 một trong số các annotation của spring boot và spring core, các annotation dành cho spring-data, spring-mvc, spring-message mình sẽ nói ở những bài viết sắp tới nhé

Ví dụ

Để rõ hơn về cách sử dụng các annotation, chúng ta sẽ cùng làm ví dụ "xin chào".

Lớp chứa hàm main

Đây là lớp sẽ khởi động chương trình, ở lớp này chúng ta cần có @SpringBootApplication annotation. Chúng ta cũng có thể sử dụng các annotation @PropertySource hay @ComponentScan ở đây.

package com.example.spring.boot;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.PropertySource;
import com.example.spring.boot.service.GreetService;
@SpringBootApplication
@PropertySource("classpath:application.yaml")
public class SpringBootExample {
    public static void main(String[] args) {
        ApplicationContext appContext = SpringApplication.run(SpringBootExample.class);
        GreetService greetService = appContext.getBean(GreetService.class);
        System.out.println(greetService.greet("youngmonkeys"));
    }
}

Lớp dữ liệu

package com.example.spring.boot.entity;
import lombok.AllArgsConstructor;
import lombok.Getter;
@Getter
@AllArgsConstructor
public class UserEntity {
    private String username;
    private String firstName;
    private String lastName;
}

Lớp xử lý dữ liệu

package com.example.spring.boot.processor;
import org.springframework.stereotype.Component;
@Component
public class UserProcessor {
    public String makeFullName(String firstName, String lastName) {
        return firstName + " " + lastName;
    }
}

Lớp truy vấn dữ liệu

package com.example.spring.boot.repository;
import org.springframework.stereotype.Repository;
import com.example.spring.boot.entity.UserEntity;
@Repository
public class UserRepository {
    public UserEntity findByUsername(String username) {
        return new UserEntity(username, "Young", "Monkeys");
    }
}

Lớp xử lý nghiệp vụ

package com.example.spring.boot.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import com.example.spring.boot.entity.UserEntity;
import com.example.spring.boot.processor.UserProcessor;
import com.example.spring.boot.repository.UserRepository;
@Service
public class GreetService {
    @Value("${greet}")
    private String greet;
    @Autowired
    private UserRepository greetRepository;
    @Autowired
    private UserProcessor userProcessor;
    public String greet(String username) {
        UserEntity user = greetRepository.findByUsername(username);
        String userFullName = userProcessor.makeFullName(user.getFirstName(), user.getLastName());
        return greet + " " + userFullName;
    }
}

Bạn có thể thấy mỗi lớp có một chức năng và nhiệm vụ riêng, và tương ứng với nó chúng ta cũng sẽ sử dụng các annotation khác nhau.

Tham khảo

  1. Spring annotations