Bài 13: Xây dựng annotation và aspect tùy biến

Mục tiêu bài học
Tạo custom annotation (e.g. @AuditLog): Học cách định nghĩa annotation mới để sử dụng trong các method hoặc class.
Truyền tham số vào annotation: Hiểu cách truyền tham số động vào annotation để tăng tính linh hoạt.
Áp dụng vào dự án lớn (logging, auditing, event trigger): Xây dựng các use case thực tế, chẳng hạn logging hoặc kích hoạt sự kiện.
Nội dung chính
1. Custom Annotation
Cách định nghĩa annotation:
- Sử dụng các annotation meta như
@Retention
,@Target
để chỉ định phạm vi và mục đích sử dụng.
- Sử dụng các annotation meta như
Ví dụ:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface AuditLog {
String action() default "";
String level() default "INFO";
}
2. Aspect bắt annotation
Tạo Aspect để xử lý logic liên quan:
- Dùng
@Around
,@Before
, hoặc@After
để bắt và xử lý các method có annotation.
- Dùng
Ví dụ:
@Aspect
@Component
public class AuditAspect {
@Around("@annotation(auditLog)")
public Object handleAuditLog(ProceedingJoinPoint joinPoint, AuditLog auditLog) throws Throwable {
String action = auditLog.action();
String level = auditLog.level();
System.out.println("Audit action: " + action + ", Level: " + level);
Object result = joinPoint.proceed();
System.out.println("Audit completed for action: " + action);
return result;
}
}
3. Ví dụ thực tế
Use case: Ghi log khi tạo mới user:
Đánh dấu method tạo user với
@AuditLog
.Tự động ghi log khi method được gọi.
Code mẫu:
@Service
public class UserService {
@AuditLog(action = "CREATE_USER", level = "INFO")
public void createUser(User user) {
System.out.println("Creating user: " + user.getName());
// Logic tạo user
}
}
- Output (log):
Audit action: CREATE_USER, Level: INFO
Creating user: John Doe
Audit completed for action: CREATE_USER
4. Truyền tham số động
Lấy tham số của method hoặc context hiện tại:
- Sử dụng
JoinPoint
để lấy tham số và thông tin cần thiết từ method.
- Sử dụng
Ví dụ:
@Aspect
@Component
public class DynamicAuditAspect {
@Around("@annotation(auditLog)")
public Object handleDynamicAudit(ProceedingJoinPoint joinPoint, AuditLog auditLog) throws Throwable {
Object[] args = joinPoint.getArgs();
String action = auditLog.action();
System.out.println("Action: " + action + ", Params: " + Arrays.toString(args));
Object result = joinPoint.proceed();
System.out.println("Action completed: " + action);
return result;
}
}
- Kết hợp thêm thông tin từ UserContext (e.g. User ID, IP):
String currentUser = UserContext.getCurrentUser();
System.out.println("Current user: " + currentUser);
5. Test custom annotation
Viết unit test cho Aspect và annotation:
- Kiểm tra xem Aspect có bắt đúng annotation và thực thi đúng logic không.
JUnit Example:
@SpringBootTest
@ExtendWith(MockitoExtension.class)
class AuditAspectTest {
@Mock
private UserService userService;
@Test
void testAuditLog() {
User user = new User("John Doe");
userService.createUser(user);
Mockito.verify(userService).createUser(user);
// Check log hoặc logic của aspect
}
}
6. Best Practices for Custom Annotation
Giữ annotation đơn giản, rõ mục đích:
- Tránh việc sử dụng annotation cho nhiều mục đích khác nhau.
Document annotation:
- Cung cấp tài liệu cho đội ngũ về cách sử dụng annotation, các tham số cần thiết, và mục đích sử dụng.
Tối ưu hiệu suất:
- Đảm bảo aspect chỉ chạy trên các method cần thiết, tránh ảnh hưởng đến hiệu suất.
Tóm tắt
Tạo và sử dụng custom annotation với Aspect: Học cách xây dựng annotation để xử lý các logic chung như logging, auditing.
Tăng tính linh hoạt với tham số động: Truyền tham số từ context hoặc method để xử lý logic phù hợp với ngữ cảnh.
Sang Bài 14: Học cách kiểm thử (testing) AOP để đảm bảo các aspect và annotation hoạt động đúng.
Câu hỏi thảo luận
Bạn đã từng tích hợp event streaming (Kafka) với annotation-based AOP chưa?
- Ví dụ: Annotation
@SendToKafka
để tự động gửi sự kiện sau khi method hoàn tất.
- Ví dụ: Annotation
Khi nào nên tách annotation thành library dùng chung?
- Khi các annotation và aspect được sử dụng trong nhiều dự án hoặc module khác nhau.
Subscribe to my newsletter
Read articles from hoangkim directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
