Spring AOP: Sự khác biệt giữa JoinPoint và PointCut là gì?


88

Tôi đang tìm hiểu các khái niệm về Lập trình hướng theo khía cạnh và Spring AOP. Tôi không hiểu sự khác biệt giữa Pointcut và Joinpoint - cả hai đều giống nhau đối với tôi. Pointcut là nơi bạn áp dụng lời khuyên của mình và điểm tham gia cũng là nơi chúng tôi có thể áp dụng lời khuyên của mình. Sau đó, sự khác biệt là gì?

Ví dụ về một pointcut có thể là:

@Pointcut("execution(* * getName()")

Ví dụ về điểm tham gia là gì?

Câu trả lời:


161

Điểm tham gia: Điểm tham gia là một điểm ứng viên trong Thực thi chương trình của ứng dụng nơi một khía cạnh có thể được cắm vào. Điểm này có thể là một phương thức đang được gọi, một ngoại lệ đang được đưa ra hoặc thậm chí một trường đang được sửa đổi. Đây là những điểm mà mã khía cạnh của bạn có thể được chèn vào luồng thông thường của ứng dụng để thêm hành vi mới.

Lời khuyên: Đây là một đối tượng bao gồm các lệnh gọi API đến các mối quan tâm của toàn hệ thống đại diện cho hành động cần thực hiện tại một điểm tham gia được chỉ định bởi một điểm.

Pointcut: Một pointcut xác định tại những điểm nối nào, Lời khuyên liên quan sẽ được áp dụng. Lời khuyên có thể được áp dụng tại bất kỳ điểm tham gia nào được hỗ trợ bởi khuôn khổ AOP. Tất nhiên, bạn không muốn áp dụng tất cả các khía cạnh của mình ở tất cả các điểm tham gia có thể có. Các phím tắt cho phép bạn chỉ định nơi bạn muốn áp dụng lời khuyên của mình. Thường thì bạn chỉ định các phím tắt này bằng cách sử dụng tên lớp và phương thức rõ ràng hoặc thông qua biểu thức chính quy xác định các mẫu tên phương thức và lớp phù hợp. Một số khuôn khổ AOP cho phép bạn tạo các con trỏ động xác định xem có áp dụng lời khuyên dựa trên các quyết định về thời gian chạy hay không, chẳng hạn như giá trị của các tham số phương thức.

Hình ảnh sau đây có thể giúp bạn hiểu về Tư vấn, ĐiểmCut, Điểm tham gia. nhập mô tả hình ảnh ở đây

Nguồn

Giải thích bằng cách sử dụng Phép tương tự nhà hàng: Nguồn của @Victor

Khi bạn đi đến một nhà hàng, bạn nhìn vào menu và thấy một số tùy chọn để lựa chọn. Bạn có thể gọi một hoặc nhiều món trong thực đơn. Nhưng cho đến khi bạn thực sự gọi chúng, chúng chỉ là "cơ hội để dùng bữa". Khi bạn đặt món và người phục vụ mang đến bàn của bạn, đó là một bữa ăn.

Điểm tham gia là các tùy chọn trên menu và Điểm cắt là các mục bạn chọn.

Điểm tham gia là một cơ hội trong mã để bạn áp dụng một khía cạnh ... chỉ là một cơ hội. Khi bạn tận dụng cơ hội đó và chọn một hoặc nhiều Điểm tham gia và áp dụng một khía cạnh cho chúng, bạn đã có Pointcut.

Nguồn Wiki :

Điểm nối là một điểm trong luồng điều khiển của chương trình nơi luồng điều khiển có thể đến qua hai con đường khác nhau (IMO: đó là lý do tại sao gọi kết nối).

Lời khuyên mô tả một lớp chức năng sửa đổi các chức năng khác

Một pointcut là một tập hợp tham gia điểm.


3
Đây phải được đánh dấu là câu trả lời đúng. Chỉ để thêm một số thông tin khác, hãy xem câu trả lời của Cragi Walls ... coderanch.com/t/485525/Spring/Difference-Joint-Point-Point-Cut .
Victor

2
Vào vấn đề: Một pointcut định nghĩa vào những gì joinpoints lời khuyên nên sử dụng 1
Naman Gala

Chỉ để xác nhận, more Joinpoints and apply an aspect to them, you've got a Pointcut. khía cạnh cho họ hoặc lời khuyên cho họ?
Asif Mushtaq

@Premraj Vì vậy, theo lời khuyên tương tự của bạn sẽ là đặt bữa ăn. Tôi nói đúng chứ?
Vishwas Atrey

Tương tự nhà hàng đã giúp xóa nhầm lẫn giữa JoinPoints và pointcuts, Cảm ơn!
SM

30

Để hiểu sự khác biệt giữa điểm nối và đường cắt điểm, hãy nghĩ các phím tắt như chỉ định các quy tắc dệt và các điểm nối như các tình huống thỏa mãn các quy tắc đó.

Trong ví dụ dưới đây,

  @Pointcut("execution(* * getName()")  

Pointcut định nghĩa các quy tắc nói rằng, lời khuyên nên được áp dụng trên phương thức getName () có trong bất kỳ lớp nào trong bất kỳ gói nào và các điểm tham gia sẽ là danh sách tất cả phương thức getName () có trong các lớp để lời khuyên có thể được áp dụng trên các phương thức này.

(Trong trường hợp Mùa xuân, Quy tắc sẽ chỉ được áp dụng trên các hạt được quản lý và lời khuyên chỉ có thể được áp dụng cho các phương pháp công khai).


1
"Pointcut định nghĩa các quy tắc nói rằng, lời khuyên nên được áp dụng trên phương thức getName () có trong bất kỳ lớp nào trong bất kỳ gói nào và các điểm tham gia sẽ là danh sách tất cả phương thức getName () có trong các lớp để lời khuyên có thể được áp dụng trên các phương thức này." Tôi xin lỗi nhưng điều này ngày càng khó hiểu. Bạn có thể vui lòng cho tôi một phép loại suy trong một kịch bản cuộc sống hàng ngày trong thế giới thực được không?
Saurabh Patil

28

JoinPoints: Về cơ bản, đây là những vị trí trong logic nghiệp vụ thực tế mà bạn muốn chèn một số chức năng khác cần thiết nhưng không phải là một phần của logic nghiệp vụ thực tế. Một số ví dụ về JoinPints ​​là: gọi phương thức, phương thức trả về bình thường, phương thức ném một ngoại lệ, khởi tạo một đối tượng, tham chiếu một đối tượng, v.v.

Pointcuts: Pointcuts là một cái gì đó giống như biểu thức chính quy được sử dụng để xác định các điểm tham gia. Pontcuts được thể hiện bằng "ngôn ngữ biểu thức pointcut". Pointcuts là các điểm của luồng thực thi mà mối quan tâm xuyên suốt cần được áp dụng. Có một sự khác biệt giữa Joinpoint và Pointcut; Các điểm tham gia tổng quát hơn và đại diện cho bất kỳ luồng kiểm soát nào mà chúng tôi 'có thể chọn' đưa ra mối quan tâm xuyên suốt trong khi các điểm liên kết xác định các điểm tham gia đó mà 'chúng tôi muốn' đưa ra mối quan tâm xuyên suốt.


1
Joinpoint - Các địa điểm tiềm năng để áp dụng / chạy mã tư vấn. Pointcut - các điểm nối được chọn thực tế để thực hiện lời khuyên.
user104309

24

Lời giải thích của giáo dân cho một số người chưa quen với các khái niệm AOP. Điều này không phải là đầy đủ, nhưng sẽ giúp nắm bắt các khái niệm. Nếu bạn đã quen với các biệt ngữ cơ bản, bạn có thể ngừng đọc ngay bây giờ.

Giả sử bạn có một Nhân viên lớp bình thường và bạn muốn làm gì đó mỗi khi các phương thức này được gọi.

class Employee{
    public String getName(int id){....}
    private int getID(String name){...}
}

những phương thức này được gọi là JoinPoints . Chúng ta cần một cách để xác định các phương thức này để khung công tác có thể tìm thấy các phương thức, trong số tất cả các lớp. Phương thức mà nó đã tải. Vì vậy, chúng tôi sẽ viết một biểu thức chính quy để khớp với chữ ký của các phương thức này. Mặc dù có nhiều thứ hơn như bạn sẽ thấy bên dưới, nhưng một cách lỏng lẻo thì biểu thức chính quy này là thứ định nghĩa Pointcut . ví dụ

* * mypackage.Employee.get*(*)

Đầu tiên * dành cho bổ ngữ công khai / riêng tư / bảo vệ / mặc định. Thứ hai * dành cho kiểu trả về của phương thức.

Nhưng sau đó bạn cũng cần nói thêm hai điều:

  1. Khi nào nên thực hiện một hành động - ví dụ: Trước / Sau khi thực hiện phương thức HOẶC ngoại lệ
  2. nên làm gì khi nó khớp (có thể chỉ in một tin nhắn)

Sự kết hợp của hai điều này được gọi là Lời khuyên .

Như bạn có thể tưởng tượng, bạn sẽ phải viết một hàm để có thể thực hiện # 2. Vì vậy, đây là cách nó có thể trông như thế nào đối với những điều cơ bản.

Lưu ý: Để rõ ràng, hãy sử dụng từ REGEX thay vì * * mypackage.Employee.get*(*). Trong thực tế, biểu thức đầy đủ đi vào định nghĩa.

@Before("execution(REGEX)")
public void doBeforeLogging() {....}   <-- executed before the matching-method is called

@After("execution(REGEX)")
public void doAfterLogging() {....}  <-- executed after the matching-method is called

Một khi bạn bắt đầu sử dụng chúng một chút, bạn có thể sẽ chỉ định nhiều lời khuyên @ After / @ Before / @ Around. Các biểu thức chính quy lặp đi lặp lại cuối cùng sẽ khiến mọi thứ trở nên khó hiểu và khó duy trì. Vì vậy, những gì chúng tôi làm, chúng tôi chỉ đặt tên cho biểu thức và sử dụng nó ở mọi nơi khác trong lớp Aspect.

@Pointcut("execution(REGEX)") <-- Note the introduction of Pointcut keyword
public void allGetterLogging(){} <-- This is usually empty

@Before("allGetterLogging")
public void doBeforeLogging() {....}

@After("allGetterLogging")
public void doAfterLogging() {....}

BTW, bạn cũng muốn gói toàn bộ logic này trong một lớp, được gọi là Aspect và bạn sẽ viết một lớp:

@Aspect
public class MyAwesomeAspect{....}

Để tất cả những thứ này hoạt động, bạn phải yêu cầu Spring phân tích cú pháp các lớp để đọc, hiểu và thực hiện hành động trên các từ khóa @ AOP. Một cách để làm điều đó là chỉ định những điều sau trong tệp xml cấu hình mùa xuân:

<aop:aspectj-autoproxy>


1
Tôi mới làm quen với AOP và lời giải thích này đã giúp tôi hiểu khá rõ ràng mối quan hệ giữa các Lời khuyên / Pointcuts / JoinPoints.
Jatin Shashoo

11

So sánh ngôn ngữ AOP như AspectJ với ngôn ngữ truy vấn dữ liệu như SQL, bạn có thể nghĩ về các điểm tham gia (tức là tất cả các vị trí trong mã của bạn nơi bạn có thể đan mã khía cạnh) như một bảng cơ sở dữ liệu với nhiều hàng. Một pointcut giống như một stamement SELECT có thể chọn một tập hợp con của các hàng / điểm nối do người dùng xác định. Mã thực tế bạn dệt vào những nơi đã chọn đó được gọi là lời khuyên.


9

Định nghĩa

Theo tài liệu:

Tham gia điểm: một điểm trong quá trình thực thi một chương trình, chẳng hạn như thực thi một phương thức hoặc xử lý một ngoại lệ.

Bạn có thể coi Điểm chung là sự kiện trong quá trình thực hiện một chương trình. Nếu bạn đang sử dụng Spring AOP, điều này thậm chí còn bị giới hạn trong việc gọi các phương thức. AspectJ cung cấp tính linh hoạt hơn.

Nhưng bạn không bao giờ xử lý tất cả các sự kiện vì bạn không ăn hết thức ăn trong thực đơn khi đến một nhà hàng (tôi không biết bạn, bạn có thể! Nhưng, tôi chắc chắn không). Vì vậy, bạn thực hiện lựa chọn các sự kiện để xử lý và phải làm gì với chúng. Đây là Pointcuts . Theo tài liệu,

Pointcut : một vị từ khớp với các điểm nối .

Sau đó, bạn liên kết những gì cần làm với Pointcut , sẽ có Lời khuyên . Theo tài liệu,

Lời khuyên được liên kết với một biểu thức pointcut và chạy tại bất kỳ điểm nối nào được so khớp với pointcut.

package com.amanu.example;

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

/**
 * @author Amanuel Nega on 10/25/16.
 */
class ExampleBussinessClass {

    public Object doYourBusiness() {
        return new Object();
    }

}

@Aspect
class SomeAspect {

    @Pointcut("execution(* com.amanu.example.ExampleBussinessClass.doYourBusiness())")
    public void somePointCut() {
    }//Empty body suffices

    @After("somePointCut()")
    public void afterSomePointCut() {
        //Do what you want to do after the joint point is executed
    }

    @Before("execution(* *(*))")
    public void beforeSomePointCut() {
        //Do what you want to do before the joint point is executed
    }

}

Giải thích mã

  • ExampleBusinessClass khi proxy-ed, là mục tiêu của chúng tôi!
  • doYourBusiness()là một điểm chung khả thi
  • SomeAspect là khía cạnh của chúng tôi có liên quan đến nhiều mối quan tâm như ass ExampleBusinessClass
  • somePointCut()là định nghĩa của một điểm cắt khớp với điểm chung của chúng ta
  • afterSomePointCut()là một lời khuyên sẽ được thực hiện sau khi somePointCut điểm cắt của chúng tôi khớp với doYourBusiness() điểm chung
  • beforeSomePointCut()cũng là một lời khuyên phù hợp với tất cả các lần publicthực thi phương pháp. Không giống như afterSomePointCut, cái này sử dụng khai báo điểm cắt nội tuyến

Bạn có thể xem tài liệu nếu bạn không tin tôi. Tôi hi vọng cái này giúp được


1
Giải thích đơn giản. Chỉ ba đoạn trích dẫn là đủ để hiểu. Cảm ơn.
TRiNE

6

Cả hai đều liên quan đến "vị trí" của lập trình hướng khía cạnh.

Điểm tham gia là một nơi riêng lẻ mà bạn có thể thực thi mã với AOP. Ví dụ: "khi một phương thức ném một ngoại lệ".

Pointcut là một tập hợp các điểm tham gia. Ví dụ: "khi một phương thức trong lớp Foo ném một ngoại lệ".


4

JoinPoint : Joinpoint là các điểm trong quá trình thực thi chương trình của bạn nơi luồng thực thi đã thay đổi như bắt ngoại lệ, Gọi phương thức khác.

PointCut : PointCut về cơ bản là những Điểm tham gia mà bạn có thể đưa ra lời khuyên của mình (hoặc khía cạnh cuộc gọi).

Vì vậy, về cơ bản PointCuts là tập con của JoinPoints .


3

AOP vào mùa xuân có {Advisor, Consulting, Pointcut, Joinpoint}

Như bạn đã biết mục đích chính của aop là tách logic mối quan tâm xuyên suốt (Phương diện) khỏi mã ứng dụng, để thực hiện điều này trong Spring, chúng tôi sử dụng (Lời khuyên / Cố vấn)

Pointcut được sử dụng để lọc nơi chúng tôi muốn áp dụng chính xác lời khuyên này, chẳng hạn như "tất cả các phương pháp bắt đầu bằng chèn", vì vậy các phương pháp khác sẽ bị loại trừ, đó là lý do tại sao chúng tôi có trong giao diện Pointcut {ClassFilter và MethodMatcher}

Vì vậy, Lời khuyên là sự thực hiện logic xuyên suốt và Cố vấn là lời khuyên cộng với PointCut, nếu bạn chỉ sử dụng lời khuyên, mùa xuân sẽ ánh xạ nó đến người cố vấn và làm cho pointcut ĐÚNG có nghĩa là không chặn bất cứ thứ gì. Đó là lý do tại sao khi bạn chỉ sử dụng lời khuyên, nó được áp dụng cho tất cả các phương thức của lớp đích vì bạn đã không lọc chúng.

Nhưng Joinpoint là một vị trí trong chương trình, bạn có thể nghĩ về nó giống như phản chiếu khi bạn truy cập đối tượng Class và sau đó bạn có thể nhận được đối tượng Method, sau đó bạn có thể gọi bất kỳ phương thức nào trong lớp này và đó là cách trình biên dịch hoạt động, nếu bạn nghĩ như điều này bạn có thể hình dung về điểm tham gia.

Joinpoint có thể là với trường, hàm tạo hoặc phương thức nhưng trong Spring chúng ta chỉ có joinpoint với các phương thức, đó là lý do tại sao trong Spring chúng ta có các loại Joinpoint (Before, After, Throws, Around), tất cả chúng đều đề cập đến các vị trí trong lớp.

Như tôi đã đề cập, bạn có thể có lời khuyên không có pointcut (không có bộ lọc) thì nó sẽ được áp dụng cho tất cả các phương pháp hoặc bạn có thể có người tư vấn là [lời khuyên + pointcut] sẽ được áp dụng cho các phương pháp cụ thể nhưng bạn không thể có lời khuyên mà không có joinpoint giống như pointcut, bạn phải chỉ định nó, và đó là lý do tại sao các loại lời khuyên trong mùa xuân giống hệt như các loại điểm tham gia, vì vậy khi bạn chọn một lời khuyên, bạn mặc nhiên chọn điểm tham gia nào.

Tóm lại, lời khuyên là logic triển khai cho khía cạnh của bạn đối với lớp mục tiêu, lời khuyên này nên có một điểm tham gia như trước khi gọi, sau khi gọi, sau khi ném hoặc xung quanh lời gọi, sau đó bạn có thể lọc nơi chính xác bạn muốn áp dụng nó bằng cách sử dụng pointcut để lọc các phương thức hoặc không có pointcut (không có bộ lọc) nên nó sẽ được áp dụng cho tất cả các phương thức của lớp.


3

Một pointcut được định nghĩa trên việc triển khai Aspect - class. Point cut về cơ bản đề cập đến biểu thức pointcut trong lời khuyên.

Ví dụ,

@Before("execution(* app.purchase2.service.impl.*(..))")
public void includeAddOns(RolesAllowed roles) {
..
}

Ở trên có nghĩa là, phương thức "includeAddOns" được gọi trước khi gọi (do lời khuyên @Before) bất kỳ phương thức nào (trong các lớp bên trong gói "app.purchase2.service.impl")

Toàn bộ chú thích được gọi là pointcut @Before("execution(* app.purchase2.service.impl.*(..))")

Điểm liên kết là lệnh gọi phương thức thực tế, đã nối phương thức trong gói "app.purchase2.service.impl" với phương thức trong lớp khía cạnh "includeAddOns ()".

Bạn có thể truy cập các thuộc tính của điểm nối với org.aspectj.lang.JoinPointlớp.


Câu trả lời tốt! Cuối cùng tôi đã hiểu sự khác biệt!
Dante

2

Tôi đồng ý với mgroves .. Một điểm cắt có thể được coi là tập hợp của nhiều điểm nối. Điểm chung chỉ định vị trí cụ thể nơi lời khuyên có thể được thực hiện, nơi mà pointcut phản ánh danh sách tất cả các điểm chung.


0

JoinPoint: Nó chỉ định một điểm (phương thức) trong ứng dụng nơi Lời khuyên sẽ được thực thi.

Pointcut: Đó là sự kết hợp của các JoinPoint và nó chỉ định rằng tại đó Lời khuyên của JoinPoint sẽ được thực thi.


-5

điểm tham gia là nơi chúng tôi thực sự đưa ra các lời khuyên

nhưng điểm cắt là tập hợp các điểm nối. điều đó có nghĩa là có bao nhiêu cách chúng ta đặt logic cắt ngang được gọi là điểm cắt

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.