Aspect-oriented programming (AOP)

Aspect-oriented programming (AOP)

Như bạn đã biêt về Spring context và DI capability, framework quản lý các đối tượng bạn xác định và bạn có thể yêu cầu sử dụng các đối tượng này nơi bạn cần. Trong bài viết này tôi sẽ giới thiệu một kỹ thuật mạnh mẽ khác được hỗ trợ bởi IOC principle : aspects.

Aspects là một cách mà framwork chặn các cuộc gọi method và có thể thay đổi việc thực thi các method. Bạn có thể tác động đến việc thực hiện các lệnh gọi method cụ thể mà bạn chọn. Kỹ thuật này giúp bạn trích xuất 1 phần logic của method thực thi. Trong 1 số trường hợp nhất định, việc tách rời 1 phần code giúp làm cho method đó dễ hiểu hơn. Nó cho phép developer chỉ tập trung vào các chi tiết liên quan được thảo luận khi đọc method logic.

Aspects là 1 công cụ mạnh mẽ, và như chú của Peter Parker nói, "With great power comes great responsibility!”. Nếu bạn không sử dụng aspects 1 cách cẩn thận, bạn có thể nhận được 1 ứng dụng khó bảo trì, điều này hoàn toàn trái ngược với những gì bạn muốn đạt được. Cách tiếp cận này được gọi là aspect-oriented programming (AOP).

Một lý do quan trọng khác cho việc tìm hiểu aspects là Spring sử dụng chúng để triển khai rất nhiều khả năng quan trọng mà nó cung cấp. Hiểu cách hoạt động của framework có thể giúp bạn tiết kiệm nhiều giờ debug sau này khi bạn gặp phải một vấn đề cụ thể. Một ví dụ thích hợp về khả năng của Spring sử dụng aspect là transactionality. Transactionality là một trong những khả năng chính mà hầu hết các ứng dụng sử dụng ngày nay để duy trì tính nhất quán của dữ liệu (persisted data’s consistency). Một khả năng quan trọng khác dựa trên aspects là security configurations, giúp ứng dụng của bạn bảo vệ dữ liệu của ứng dụng và đảm bảo rằng những cá nhân không mong muốn không thể nhìn thấy hoặc thay đổi dữ liệu. Để hiểu đúng những gì xảy ra trong các ứng dụng sử dụng chức năng này, trước tiên bạn cần tìm hiểu aspects.

Đôi khi, cần có những đoạn code không liên quan ở cùng một nơi với business logic, nhưng cũng vì thế nó làm cho ứng dụng trở nên khó hiểu hơn. Một giải pháp là di chuyển đoạn code đó ra khỏi triển khai business logic bằng cách sử dụng aspect. Trong cảnh này, Jane, lập trình viên, không được khuyến khích bởi các dòng ghi log được viết cùng với business code. Bá tước Dracula cho cô thấy sự kỳ diệu của aspects bằng cách tách các đoạn code ghi logs vào một aspect

How aspects work in Spring

Một aspect chỉ đơn giản là 1 phần logic mà framwork thực thi khi bạn gọi các method cụ thể mà bạn chọn. Khi thiết kế 1 aspect, bạn xác định như sau:

What - Code nào bạn muốn Spring thực thi khi bạn gọi các method cụ thể. Điều này được đặt tên là 1 aspect.

When - Thời điểm ứng dụng nên thực thi logic của aspect này (ví dụ : trước hoặc sau lệnh gọi method, thay vì lệnh gọi method). Đây được gọi là advice.

Which - Các method nào mà framwork cần chặn (interceptor) và thực thi aspect cho chúng. Điều này được đặt tên là 1 pointcut.

Với aspect, bạn cũng sẽ tìm thấy khái niệm join point, điểm này xác định sự kiện kích hoạt việc thực thi 1 aspect. Nhưng với Spring, sự kiện này luôn là 1 lời gọi method.

Như trong trường hợp DI, để sử dụng aspects, bạn cần framework để quản lý các đối tượng mà bạn muốn áp dụng aspects. Bạn phải thêm bean vào Spring context để cho phép framework kiểm soát chúng và áp dụng aspects bạn xác định. Bean khai báo method bị chặn bởi 1 aspect được đặt tên là target object. Hình dưới đây sẽ minh họa điều này.

Hình 1 - Thuật ngữ aspect. Spring thực hiện 1 số logic (the aspect) khi ai đó call 1 method cụ thể (the pointcut). Chúng ta cần chỉ định khi logic được thực thi theo pointcut. (e.g., before). Khi nào là advice. Đối với spring để chặn method, object xác định method bị chặn cần phải là 1 bean trong Spring context. Vì vậy, bean trở thành target object của aspect.

Nhưng làm thế nào Spring chặn mỗi method call và áp dụng aspect logic? Như đã thảo luận trước đó trong bài này, object cần phải là 1 bean trong Spring context. Nhưng bởi vì bạn đã biến object thành 1 aspect target, Spring không trực tiếp cung cấp cho bạn 1 instance reference cho bean khi bạn yêu cầu nó từ context. Thay vào đó, Spring cung cấp cho bạn 1 object gọi aspect logic thay vì method thực tế. Tôi nói rằng Spring cung cấp cho bạn 1 proxy object thay vì bean thật. Bây giờ bạn sẽ nhận được proxy thay vì bean bất cứ khi nào bạn nhận được bean từ context, nếu bạn trực tiếp sử dụng method getBean() của context hoặc nếu bạn sử dụng DI. Các tiếp cận này được đặt tên là weaving.

Hình 2 - Weaving 1 aspect. Thay vì cung cấp cho bạn 1 tham chiếu đến 1 bean thật, Spring cung cấp cho bạn 1 tham chiếu đến 1 đối tượng proxy, chặn các cuộc gọi method và quản lý các aspect logic.

Thêm 1 ví dụ nữa (hình 3) so sánh giữa việc gọi method khi nó không bị chặn bởi 1 aspect so với aspect chặn cuộc gọi method. Bạn quan sát thấy rằng việc gọi 1 method có aspect giả định rằng bạn gọi method đó thông qua proxy object do Spring cung cấp. Proxy áp dụng aspect logic và ủy quyền cuộc gọi đến method thực tế.

Hình 3 - Khi 1 method không được aspected, cuộc gọi sẽ chuyển trực tiếp đến method đó. Khi chúng ta định nghĩa 1 aspect cho 1 method, cuộc gọi sẽ đi qua proxy object. Proxy object áp dụng logic được xác định bởi aspect và sau đó ủy quyền cho method thật.

Bây giờ bạn đã có bức tranh toàn cảnh về aspects và cách Spring quản lý chúng. Việc còn lại bạn cần làm là học các cú pháp để implement aspects với Spring.

Chúc bạn thành công !