Spring Boot - Một số Annotation - Phần 3
Nếu đọc đến phần này, chắc hẳn bạn đã thưởng thức một hộp bánh tráng trộn tóp mỡ hay đại loại một món ăn ngon lành cành đào đó. Vậy là quá dư năng lượng để tiếp tục tìm hiểu thêm các annotion còn lại trong bài viết này.
Bài còn dài, kiến thức còn bao la để đọc và học. Tranh thủ đọc bài thôiii.
20. @Cacheable
@Cacheable được sử dụng để lưu trữ kết quả của một phương thức vào bộ nhớ cache. Nếu phương thức đó được gọi lại với cùng tham số, kết quả sẽ được lấy từ cache thay vì thực thi lại phương thức. Điều này rất hữu ích để tối ưu hóa hiệu suất, đặc biệt với các thao tác đọc dữ liệu chậm từ cơ sở dữ liệu.
1
2
3
4
5
6
7
8
9
@Service
public class ProductService {
@Cacheable("products")
public Product getProductById(Long id) {
// Giả sử đây là một thao tác tốn thời gian
return productRepository.findById(id).orElseThrow();
}
}
@Cacheable giống như một cuốn sổ tay thần kỳ. Mỗi lần bạn hỏi về một món hàng, thay vì chạy đi tìm lại món đó trong kho, bạn chỉ cần mở sổ ra và nói: “Aha! Nó nằm ở đây rồi!”
21. @CacheEvict
Annotation này được dùng để xóa một hoặc nhiều cache đã được lưu trước đó khi bạn cập nhật hoặc xóa dữ liệu. Điều này đảm bảo rằng dữ liệu trong cache luôn nhất quán với dữ liệu thực tế.
1
2
3
4
5
6
7
8
9
@Service
public class ProductService {
@CacheEvict(value = "products", allEntries = true)
public void updateProduct(Product product) {
// Cập nhật sản phẩm
productRepository.save(product);
}
}
Hãy tưởng tượng @CacheEvict giống như việc bạn thay đổi nội dung trong cuốn sổ tay. Mỗi lần có thông tin mới, bạn phải xóa thông tin cũ đi để đảm bảo mọi người không bị nhầm lẫn.
22. @Conditional
@Conditional cho phép bạn tạo bean hoặc kích hoạt một cấu hình nào đó chỉ khi điều kiện nhất định được thỏa mãn. Đây là một công cụ mạnh mẽ để giúp ứng dụng của bạn linh hoạt hơn trong việc cấu hình dựa trên ngữ cảnh hoặc môi trường.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Configuration
public class DataSourceConfig {
@Bean
@Conditional(OnProductionCondition.class)
public DataSource productionDataSource() {
return new MySQLDataSource();
}
@Bean
@Conditional(OnDevelopmentCondition.class)
public DataSource developmentDataSource() {
return new H2DataSource();
}
}
@Conditional giống như người bảo vệ ở cửa vào câu lạc bộ. Bạn chỉ được vào nếu bạn đáp ứng các tiêu chí (như mặc đúng dress code hay có thẻ thành viên). Không đáp ứng điều kiện? Bạn phải đợi ở ngoài!
23. @PreAuthorize và @PostAuthorize
@PreAuthorize và @PostAuthorize là hai annotation được sử dụng để thực hiện việc kiểm soát truy cập dựa trên các điều kiện trước và sau khi phương thức được gọi. Chúng được sử dụng rộng rãi trong Spring Security để xác định ai có quyền truy cập vào một phương thức cụ thể.
@PreAuthorize: Được kiểm tra trước khi thực hiện phương thức.@PostAuthorize: Được kiểm tra sau khi thực hiện phương thức.
1
2
3
4
5
6
7
8
9
10
11
12
13
@Service
public class UserService {
@PreAuthorize("hasRole('ADMIN')")
public List<User> getAllUsers() {
return userRepository.findAll();
}
@PostAuthorize("returnObject.username == authentication.name")
public User getUserDetails(Long id) {
return userRepository.findById(id).orElseThrow();
}
}
@PreAuthorize giống như người bảo vệ cửa câu lạc bộ. Trước khi bạn vào, họ sẽ kiểm tra giấy tờ để đảm bảo rằng bạn đủ điều kiện. Còn @PostAuthorize giống như người kiểm tra hóa đơn sau khi bạn đã vào và tận hưởng dịch vụ: “Khoan đã, xem bạn có đủ tiền trả không nào!”
24. @Retryable
@Retryable được sử dụng để tự động thử lại một phương thức khi có lỗi xảy ra, đặc biệt là với các thao tác không đồng bộ hoặc gọi API. Bạn có thể cấu hình số lần thử lại, thời gian chờ giữa các lần thử, và những lỗi nào sẽ kích hoạt việc thử lại.
1
2
3
4
5
6
7
8
9
@Service
public class ExternalService {
@Retryable(value = { IOException.class }, maxAttempts = 3, backoff = @Backoff(delay = 2000))
public String callExternalAPI() throws IOException {
// Gọi đến một API bên ngoài
throw new IOException("API không phản hồi");
}
}
@Retryable giống như khi bạn gọi điện mà không ai nghe máy, bạn tiếp tục gọi lại lần nữa và lần nữa, với hy vọng rằng một lúc nào đó người ta sẽ bắt máy!
25. @EnableScheduling
Annotation này cho phép bật tính năng lập lịch trong Spring Boot, giúp các tác vụ có thể được thực hiện tự động theo thời gian bạn định sẵn. Để sử dụng các annotation như @Scheduled, bạn cần bật tính năng này trong cấu hình của ứng dụng.
1
2
3
4
5
@Configuration
@EnableScheduling
public class SchedulingConfig {
// cấu hình liên quan đến scheduling
}
@EnableScheduling giống như bạn bật đồng hồ báo thức cho tất cả các công việc hằng ngày. Nó sẽ nhắc nhở bạn rằng đã đến lúc thực hiện công việc nào đó theo thời gian đã định.
26. @ConditionalOnProperty
Annotation này cho phép bật hoặc tắt một bean dựa trên một thuộc tính (property) trong file cấu hình. Đây là cách tuyệt vời để kích hoạt hoặc vô hiệu hóa các tính năng khác nhau của ứng dụng tùy thuộc vào môi trường hoặc cấu hình.
1
2
3
4
5
@Bean
@ConditionalOnProperty(name = "feature.toggled", havingValue = "true")
public FeatureService featureService() {
return new FeatureService();
}
Hãy tưởng tượng bạn có một chiếc công tắc trong nhà, và chỉ khi công tắc này được bật (thuộc tính feature.toggled là true), đèn (bean) mới được bật sáng. Nếu không, đèn sẽ không bao giờ sáng!
27. @ConditionalOnMissingBean
Annotation này được sử dụng để định nghĩa một bean chỉ khi chưa có bean nào cùng loại đã được định nghĩa trong container. Điều này rất hữu ích khi bạn muốn cung cấp một bean mặc định nhưng vẫn để ngỏ khả năng người dùng tự định nghĩa bean của họ.
1
2
3
4
5
@Bean
@ConditionalOnMissingBean
public DefaultService defaultService() {
return new DefaultServiceImpl();
}
@ConditionalOnMissingBean giống như bạn định sẵn kế hoạch cho một bữa tiệc. Nếu không ai mang đồ uống, bạn sẽ tự mang đồ uống của mình, nhưng nếu ai đó đã mang rồi, bạn có thể thư giãn và để họ lo phần đó.
28. @EnableAspectJAutoProxy
@EnableAspectJAutoProxy cho phép tự động bật tính năng AOP (Aspect-Oriented Programming) trong Spring Boot. AOP cho phép bạn thêm logic bổ sung vào các phương thức mà không cần thay đổi mã nguồn chính của chúng, thông qua các “aspect” (khía cạnh) như logging, giao dịch, bảo mật, v.v.
1
2
3
4
5
@Configuration
@EnableAspectJAutoProxy
public class AopConfig {
// Cấu hình liên quan đến AOP
}
@EnableAspectJAutoProxy giống như việc bạn đeo một chiếc kính đặc biệt, giúp bạn nhìn thấy tất cả các chi tiết đằng sau hậu trường (như logging hoặc bảo mật) mà người khác không thể nhìn thấy trực tiếp trong mã nguồn.
29. @ComponentScan
@ComponentScan cho phép Spring tự động phát hiện các bean trong package và các sub-package của nó. Điều này giúp Spring biết nơi để tìm kiếm các class được đánh dấu với các annotation như @Component, @Service, @Repository, và @Controller.
1
2
3
4
5
@Configuration
@ComponentScan(basePackages = "com.example.app")
public class AppConfig {
// cấu hình ứng dụng
}
Hãy tưởng tượng @ComponentScan giống như một người tìm kiếm kho báu. Họ sẽ đi khắp nơi trong khu vực đã định để tìm kiếm các kho báu (bean) và mang chúng về.
30. @ResponseBody
@ResponseBody được sử dụng để chỉ định rằng kết quả trả về của một phương thức sẽ được đưa vào response body, thay vì trả về một view.
1
2
3
4
5
@GetMapping("/products")
@ResponseBody
public List<Product> getAllProducts() {
return productService.getAllProducts();
}
@ResponseBody giống như việc bạn đang gửi một món quà. Bạn không chỉ nói rằng bạn có quà mà còn mở hộp ra cho người khác thấy bên trong!
31. @CrossOrigin
Annotation này cho phép cấu hình CORS (Cross-Origin Resource Sharing) cho các phương thức hoặc controller. Điều này rất quan trọng khi bạn phát triển ứng dụng front-end và back-end riêng biệt, vì nó cho phép truy cập tài nguyên từ các nguồn khác nhau.
1
2
3
4
5
@CrossOrigin(origins = "http://example.com")
@GetMapping("/api/products")
public List<Product> getProducts() {
return productService.getAllProducts();
}
@CrossOrigin giống như một chiếc cầu nối giữa hai bờ. Nó cho phép các yêu cầu từ một nguồn (như front-end) vượt qua và đến được với tài nguyên của bạn (như back-end).
32. @EnableTransactionManagement
Annotation này cho phép bạn kích hoạt quản lý giao dịch trong Spring. Điều này giúp đảm bảo rằng các thao tác trong database sẽ được thực hiện trong một giao dịch, và nếu có lỗi xảy ra, mọi thứ sẽ quay lại trạng thái ban đầu.
1
2
3
4
5
@Configuration
@EnableTransactionManagement
public class TransactionConfig {
// cấu hình giao dịch
}
@EnableTransactionManagement giống như một người quản lý trong một bữa tiệc lớn. Họ đảm bảo mọi thứ diễn ra suôn sẻ và nếu có điều gì không ổn, họ có thể quay ngược mọi thứ lại để mọi người không bị rắc rối.
33. RepositoryRestResource
Annotation này được sử dụng để tạo các endpoint RESTful cho các repository mà không cần phải viết controller. Đây là một phần của Spring Data REST.
1
2
3
4
@RepositoryRestResource
public interface UserRepository extends JpaRepository<User, Long> {
// tự động tạo các endpoint RESTful
}
@RepositoryRestResource giống như một người quản lý tự động hóa. Họ giúp bạn tiết kiệm thời gian và công sức bằng cách tự động làm mọi thứ cho bạn mà không cần bạn phải làm gì!
Kết luận
Với những annotation bổ sung này, bạn đã có một cái nhìn sâu hơn về cách Spring Boot hoạt động và cách mà các annotation này giúp tối ưu hóa quá trình phát triển ứng dụng. Từ việc quản lý giao dịch cho đến việc xử lý yêu cầu HTTP, từng annotation đều đóng một vai trò quan trọng trong việc tạo ra các ứng dụng hiệu quả và dễ bảo trì.
Biết và vận dụng được càng nhiều annotation hơn sẽ giúp code trông xịn xò con bò và clean, ngắn gọn hơn. Từ đó, nâng tầm và tốc độ code nhanh hơn, trông senior hơn rất chi là nhiều.
Bài viết mang tính chất “ghi chú, lưu trữ, chia sẻ và phi lợi nhuận”.
Nếu bạn thấy hữu ích, đừng quên chia sẻ với bạn bè và đồng nghiệp của mình nhé!
Happy coding! 😎 👍🏻 🚀 🔥