Spring Bean
1. Giới thiệu
Spring Framework thực hiện và thúc đẩy nguyên tắc đảo ngược điều khiển (IOC) hoặc Dependency Injection (DI) và trên thực tế là một IOC container.
Spring cho phép nhà phát triển quản lý các bean dependency bằng cách sử dụng cấu hình dựa trên XML. Có một cách khác để xác định các bean và các phụ thuộc của chúng - Phương thức này là một cấu hình dựa trên Java.
Không giống như cách tiếp cận XML, cấu hình dựa trên Java cho phép bạn quản lý các bean component theo chương trình. Đó là lý do tại sao Spring annotation được giới thiệu. Trong bài viết này, chúng ta sẽ khám phá các Spring annotation được sử dụng phổ biến nhất và cũng xem xét một số chương trình ví dụ để hiểu rõ hơn về nó.
2. Danh sách Spring Annotations
Dưới đây là một các các Annotation (chú thích) được sử dụng phổ biến trong Spring Framework.
@ComponentScan: Cấu hình package để scan các lớp có annotation configuration. Chúng ta có thể chỉ định trực tiếp tên package cơ sở bằng một trong các basePackages hoặc giá trị các đối số. Spring có thể tự động scan các package bean nếu tính năng component scanning được bật.
1
2
3
@Configuration
@ComponentScan(basePackages = "com.thecorleone.annotations")
class VehicleFactoryConfig {}
Ngoài ra, chúng ta có thể trỏ đến các lớp trong các package cơ sở với đối số basePackageClasses:
1
2
3
@Configuration
@ComponentScan(basePackageClasses = VehicleFactoryConfig.class)
class VehicleFactoryConfig {}
Cả hai đối số đều là mảng để chúng ta có thể cung cấp nhiều package cho mỗi đối số. Nếu không có đối số nào được chỉ định, quá trình scan sẽ xảy ra từ cùng một package có lớp annotation @ComponentScan.
@ComponentScan tận dụng tính năng repeating annotation của Java 8 - có nghĩa là chúng ta có thể đánh dấu một lớp nhiều lần:
1
2
3
4
@Configuration
@ComponentScan(basePackages = "com.thecorleone.annotations")
@ComponentScan(basePackageClasses = VehicleFactoryConfig.class)
class VehicleFactoryConfig {}
Ngoài ra, chúng ta có thể sử dụng @ComponentScans để chỉ định nhiều cấu hình @ComponentScan:
1
2
3
4
5
6
@Configuration
@ComponentScans({
@ComponentScan(basePackages = "com.thecorleone.annotations"),
@ComponentScan(basePackageClasses = VehicleFactoryConfig.class)
})
class VehicleFactoryConfig {}
Khi sử dụng XML configuration, việc định cấu hình component scanning sẽ trở nên dễ dàng hơn:
1
<context:component-scan base-package="com.thecorleone" />
@Configuration: Được sử dụng để chỉ ra rằng một lớp khai báo một hoặc nhiều phương thức @Bean. Các lớp này được xử lý bởi Spring container để tạo ra các định nghĩa bean và các yêu cầu dịch vụ cho các bean đó trong thời gian chạy.
@Bean: Chỉ ra rằng một phương thức tạo ra một bean được quản lý bởi Spring container. Đây là một trong những Spring Annotation được sử dụng nhiều nhất và quan trọng nhất. @Bean annotation cũng có thể được sử dụng với các tham số như name, initMethod và DestMethod.
- name - cho phép bạn đặt tên cho bean
- initMethod - cho phép bạn chọn phương thức sẽ được gọi trên context register
- killMethod - cho phép bạn chọn phương thức sẽ được gọi khi tắt context
Ví dụ:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Configuration
public class AppConfig {
@Bean(name = "comp", initMethod = "turnOn", destroyMethod = "turnOff")
Computer computer() {
return new Computer();
}
}
public class Computer {
public void turnOn(){
System.out.println("Load operating system");
}
public void turnOff(){
System.out.println("Close all programs");
}
}
@PreDestroy và @PostConstruct là những cách thay thế cho bean initMethod và DestMethod. Nó có thể được sử dụng khi lớp bean được định nghĩa bởi chúng ta.
Ví dụ:
1
2
3
4
5
6
7
8
9
10
11
12
public class Computer {
@PostConstruct
public void turnOn(){
System.out.println("Load operating system");
}
@PreDestroy
public void turnOff(){
System.out.println("Close all programs");
}
}
@Component: Cho biết rằng một lớp được chú thích (annotation) là một “component”. Các lớp như vậy được coi là ứng cử viên để tự động phát hiện khi sử dụng cấu hình dựa trên annotation và scan đường dẫn phân lớp (classpath).
1
2
3
4
@Component
class CarUtility {
// code gì đó ở đây
}
@PropertySource: Cung cấp cơ chế khai báo đơn giản để thêm nguồn thuộc tính vào Spring’s Environment. Có một annotation tương tự để thêm một mảng thuộc tính file nguồn, tức là @PropertySources.
@Service: Cho biết rằng một lớp được chú thích là một “Service”. Annotation này đóng vai trò là một specialization của @Component, cho phép các lớp triển khai được tự động phát hiện thông qua scan đường dẫn phân lớp.
1
2
3
4
@Service
public class VehicleService {
// code gì đó ở đây
}
@Repository: Cho biết rằng một lớp được chú thích là một “Repository”. Annotation này đóng vai trò là specialization của @Component và được khuyến khích sử dụng với các lớp DAO – các lớp truy cập dữ liệu Data Access Object.
1
2
3
4
@Repository
class VehicleRepository {
// code gì đó ở đây
}
@Autowired: Spring @Autowired annotation được sử dụng để tự động injection các bean. Spring @Qualifier annotation được sử dụng cùng với Autowired để tránh nhầm lẫn khi chúng ta có hai bean khác được định cấu hình cho cùng một loại.
@Annotation Stereotype và AOP: Khi chúng ta sử dụng các Spring Stereotype annotation, thật dễ dàng để tạo một pointcut nhắm mục tiêu tất cả các lớp có một Stereotype cụ thể.
Ví dụ: giả sử chúng ta muốn đo thời gian thực thi của các phương thức từ lớp DAO. Chúng ta sẽ tạo khía cạnh sau (sử dụng AspectJ annotations) tận dụng Stereotype @Repository:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Aspect
@Component
public class PerformanceAspect {
@Pointcut("within(@org.springframework.stereotype.Repository *)")
public void repositoryClassMethods() {};
@Around("repositoryClassMethods()")
public Object measureMethodExecutionTime(ProceedingJoinPoint joinPoint)
throws Throwable {
long start = System.nanoTime();
Object returnValue = joinPoint.proceed();
long end = System.nanoTime();
String methodName = joinPoint.getSignature().getName();
System.out.println(
"Execution of " + methodName + " took " +
TimeUnit.NANOSECONDS.toMillis(end - start) + " ms");
return returnValue;
}
}
Trong ví dụ trên, chúng ta đã tạo một pointcut phù hợp với tất cả các phương thức trong các lớp được chú thích bằng @Repository. Chúng ta đã sử dụng @Around để nhắm mục tiêu vào pointcut đó và xác định thời gian thực thi của các lệnh gọi phương thức khi bị chặn.
Sử dụng phương pháp này, chúng ta có thể thêm logging, quản lý hiệu suất, kiểm tra hoặc các hành vi khác vào mỗi lớp ứng dụng.
Lời kết
Trong bài viết này, chúng ta đã xem xét các mẫu Spring annotations và tìm hiểu loại ngữ nghĩa mà mỗi annotation này thể hiện.
Chúng ta cũng đã học cách sử dụng tính năng component scanning để container biết nơi tìm các lớp được anntation.
Cuối cùng - chúng ta đã thấy cách các annotation này dẫn đến một thiết kế rõ ràng, nhiều lớp và tách biệt giữa các mối quan tâm của một ứng dụng. Chúng cũng làm cho cấu hình nhỏ hơn vì chúng ta không còn cần phải xác định rõ ràng các bean theo cách thủ công.
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! 😎 👍🏻 🚀 🔥
Đọc thêm: