Spring AOP: JoinPoint และ PointCut ต่างกันอย่างไร


88

ฉันกำลังเรียนรู้แนวคิด Aspect Oriented Programming และ Spring AOP ฉันไม่เข้าใจความแตกต่างระหว่าง Pointcut และ Joinpoint - ทั้งคู่ดูเหมือนจะเหมือนกันสำหรับฉัน Pointcut คือที่ที่คุณใช้คำแนะนำของคุณและ Joinpoint ก็เป็นสถานที่ที่เราสามารถใช้คำแนะนำของเราได้ แล้วความแตกต่างคืออะไร?

ตัวอย่างของ pointcut สามารถ:

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

ตัวอย่างของ Joinpoint คืออะไร?

คำตอบ:


162

Joinpoint: joinpoint คือจุดสมัครในProgram Executionของแอปพลิเคชันที่สามารถเสียบด้านต่างๆได้จุดนี้อาจเป็นวิธีการเรียกใช้ข้อยกเว้นที่ถูกโยนหรือแม้แต่ฟิลด์ที่กำลังแก้ไข นี่คือจุดที่สามารถแทรกโค้ดของแง่มุมของคุณลงในขั้นตอนปกติของแอปพลิเคชันของคุณเพื่อเพิ่มพฤติกรรมใหม่ ๆ

คำแนะนำ:นี่คือออบเจ็กต์ที่มีการเรียก API ไปยังข้อกังวลทั้งระบบที่แสดงถึงการดำเนินการที่จุดเชื่อมที่ระบุโดยจุด

Pointcut: Pointcutกำหนดจุดเชื่อมต่อควรใช้คำแนะนำที่เกี่ยวข้อง สามารถใช้คำแนะนำได้ที่จุดเชื่อมต่อใดก็ได้ที่รองรับโดยกรอบงาน AOP แน่นอนคุณไม่ต้องการใช้ทุกแง่มุมของคุณกับจุดเชื่อมต่อที่เป็นไปได้ทั้งหมด คำแนะนำช่วยให้คุณระบุตำแหน่งที่คุณต้องการนำคำแนะนำไปใช้ บ่อยครั้งที่คุณระบุคำสั่งชี้เหล่านี้โดยใช้ชื่อคลาสและเมธอดที่ชัดเจนหรือผ่านนิพจน์ทั่วไปที่กำหนดรูปแบบคลาสและชื่อเมธอดที่ตรงกัน เฟรมเวิร์ก AOP บางตัวช่วยให้คุณสร้างพอยต์ช็อตแบบไดนามิกที่กำหนดว่าจะใช้คำแนะนำตามการตัดสินใจรันไทม์หรือไม่เช่นค่าของพารามิเตอร์วิธีการ

ภาพต่อไปนี้สามารถช่วยให้คุณเข้าใจ Advice, PointCut, Joinpoints ป้อนคำอธิบายภาพที่นี่

ที่มา

คำอธิบายโดยใช้ Restaurant Analogy: ที่มาโดย @Victor

เมื่อคุณออกไปที่ร้านอาหารคุณจะดูเมนูและเห็นตัวเลือกมากมายให้เลือก คุณสามารถสั่งซื้ออย่างน้อยหนึ่งรายการในเมนู แต่จนกว่าคุณจะสั่งพวกเขาจริงๆพวกเขาเป็นเพียง "โอกาสในการรับประทานอาหาร" เท่านั้น เมื่อคุณสั่งซื้อและบริกรนำมาที่โต๊ะของคุณก็เป็นอาหาร

Joinpoints คือตัวเลือกในเมนูและ Pointcuts คือรายการที่คุณเลือก

Joinpoint คือโอกาสภายในโค้ดเพื่อให้คุณใช้แง่มุม ... เป็นเพียงโอกาส เมื่อคุณใช้โอกาสนั้นและเลือกจุดเข้าร่วมอย่างน้อยหนึ่งจุดและใช้แง่มุมกับพวกเขาคุณจะมี Pointcut

ที่มาWiki :

Joinpointเป็นจุดในการควบคุมการไหลของโปรแกรมที่ควบคุมการไหลสามารถเดินทางมาถึงทางสองเส้นทางที่แตกต่างกัน (IMO: ที่ว่าทำไมร่วมโทร)

คำแนะนำอธิบายถึงคลาสของฟังก์ชันที่ปรับเปลี่ยนฟังก์ชันอื่น ๆ

pointcutคือการจับคู่P attern ชุด Joinpoint เช่นการเข้าร่วมจุด


3
ควรทำเครื่องหมายว่าเป็นคำตอบที่ถูกต้อง เพียงเพื่อเพิ่มบางข้อมูลเพิ่มเติมดูที่คำตอบ Cragi กำแพง ... coderanch.com/t/485525/Spring/Difference-Joint-Point-Point-Cut
วิกเตอร์

2
ตรงประเด็น: pointcut จะกำหนดสิ่งที่ควรใช้คำแนะนำจุดเชื่อม +1
Naman Gala

เพียงเพื่อยืนยันmore Joinpoints and apply an aspect to them, you've got a Pointcut. แง่มุมหรือคำแนะนำแก่พวกเขา?
Asif Mushtaq

@Premraj ดังนั้นตามคำแนะนำการเปรียบเทียบของคุณจะสั่งอาหาร ฉันถูกไหม?
Vishwas Atrey

การเปรียบเทียบร้านอาหารช่วยขจัดความสับสนระหว่าง JoinPoints และ pointcuts ขอบคุณ!
SM

31

เพื่อให้เข้าใจถึงความแตกต่างระหว่างจุดรวมและจุดตัดให้นึกถึงคำสั่งชี้เป็นการระบุกฎการทอผ้าและจุดเข้าร่วมเมื่อสถานการณ์เป็นไปตามกฎเหล่านั้น

ในตัวอย่างด้านล่าง

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

Pointcut กำหนดกฎว่าคำแนะนำควรใช้กับเมธอด getName () ที่มีอยู่ในคลาสใด ๆ ในแพ็คเกจใด ๆ และ joinpoints จะเป็นรายการเมธอด getName () ทั้งหมดที่มีอยู่ในคลาสเพื่อให้คำแนะนำสามารถนำไปใช้กับเมธอดเหล่านี้ได้

(ในกรณีของ Spring กฎจะใช้กับถั่วที่มีการจัดการเท่านั้นและคำแนะนำสามารถใช้ได้กับวิธีการสาธารณะเท่านั้น)


1
"Pointcut กำหนดกฎว่าควรใช้คำแนะนำกับเมธอด getName () ที่มีอยู่ในคลาสใด ๆ ในแพ็กเกจใด ๆ และ joinpoints จะเป็นรายการเมธอด getName () ทั้งหมดที่มีอยู่ในคลาสเพื่อให้คำแนะนำสามารถนำไปใช้กับเมธอดเหล่านี้ได้" ฉันขอโทษ แต่สิ่งนี้กำลังสับสนมากขึ้น คุณช่วยเปรียบเทียบสถานการณ์ในชีวิตประจำวันในโลกแห่งความเป็นจริงได้ไหม
Saurabh Patil

28

JoinPoints:โดยทั่วไปแล้วสิ่งเหล่านี้เป็นสถานที่ในตรรกะทางธุรกิจจริงที่คุณต้องการแทรกฟังก์ชันเบ็ดเตล็ดบางอย่างที่จำเป็น แต่ไม่ได้เป็นส่วนหนึ่งของตรรกะทางธุรกิจที่แท้จริง ตัวอย่างบางส่วนของ JoinPints ​​ได้แก่ การเรียกใช้เมธอดวิธีการส่งคืนตามปกติวิธีการโยนข้อยกเว้นการสร้างอินสแตนซ์วัตถุการอ้างอิงวัตถุ ฯลฯ ...

Pointcuts: Pointcuts เป็นนิพจน์ทั่วไปที่ใช้เพื่อระบุจุดเชื่อมต่อ Pontcuts แสดงโดยใช้ "pointcut expression language" พอยต์ช็อตคือจุดของขั้นตอนการดำเนินการที่จำเป็นต้องนำข้อกังวลข้ามส่วนตัดมาใช้ มีความแตกต่างระหว่าง Joinpoint และ Pointcut; จุดเชื่อมต่อมีความกว้างมากขึ้นและแสดงถึงขั้นตอนการควบคุมใด ๆ ที่เรา 'อาจเลือกที่จะ' นำเสนอข้อกังวลแบบตัดขวางในขณะที่พอยต์คัทจะระบุจุดเชื่อมต่อดังกล่าวโดยที่ 'เราต้องการ' แนะนำข้อกังวลแบบตัดขวาง


1
Joinpoint - สถานที่ที่เป็นไปได้ในการใช้ / เรียกใช้รหัสคำแนะนำ Pointcut - จุดเชื่อมต่อที่เลือกจริงสำหรับดำเนินการตามคำแนะนำ
user104309

26

คำอธิบายคนธรรมดาสำหรับคนที่ยังใหม่กับแนวคิด AOP นี่ไม่ใช่ข้อมูลที่ครบถ้วนสมบูรณ์ แต่ควรช่วยในการเข้าใจแนวคิด หากคุณคุ้นเคยกับศัพท์แสงพื้นฐานแล้วคุณสามารถหยุดอ่านได้เลย

สมมติว่าคุณมีพนักงานระดับปกติและคุณต้องการทำอะไรบางอย่างทุกครั้งที่มีการเรียกวิธีการเหล่านี้

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

วิธีการเหล่านี้จะเรียกว่าJoinPoints เราต้องการวิธีในการระบุวิธีการเหล่านี้เพื่อให้เฟรมเวิร์กสามารถค้นหาเมธอดในทุกคลาสวิธีที่โหลดไว้ ดังนั้นเราจะเขียนนิพจน์ทั่วไปเพื่อให้ตรงกับลายเซ็นของวิธีการเหล่านี้ ในขณะที่มีมากขึ้นในการเป็นคุณจะเห็นด้านล่าง แต่อย่างหลวม ๆ นี้แสดงออกปกติเป็นสิ่งที่กำหนดpointcut เช่น

* * mypackage.Employee.get*(*)

First * ใช้สำหรับตัวปรับแต่ง public / private / protected / default วินาที * คือประเภทการส่งคืนของวิธีการ

แต่คุณต้องบอกอีกสองสิ่ง:

  1. ควรดำเนินการเมื่อใด - เช่นก่อน / หลังการดำเนินการตามวิธีการหรือยกเว้น
  2. สิ่งที่มันควรจะทำอย่างไรเมื่อมันตรงกับ (อาจจะเพียงแค่พิมพ์ข้อความ)

การรวมกันของสองคนนี้จะเรียกว่าแนะนำ

อย่างที่นึกออกคุณจะต้องเขียนฟังก์ชันเพื่อให้สามารถทำ # 2 ได้ นี่คือลักษณะของข้อมูลพื้นฐาน

หมายเหตุ: เพื่อความชัดเจนให้ใช้คำว่าREGEXแทน* * mypackage.Employee.get*(*). ในความเป็นจริงการแสดงออกที่สมบูรณ์จะเข้าสู่นิยาม

@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

เมื่อคุณเริ่มใช้สิ่งเหล่านี้สักหน่อยคุณอาจต้องระบุคำแนะนำ @ After / @ Before / @ Around มากมาย ซ้ำแสดงออกปกติในที่สุดก็จะจบลงด้วยการทำสิ่งที่ทำให้เกิดความสับสนและยากที่จะรักษา สิ่งที่เราทำเราเพียงแค่ตั้งชื่อให้กับนิพจน์และใช้ในที่อื่น ๆ ในคลาส 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 คุณต้องการรวมตรรกะทั้งหมดนี้ไว้ในคลาสที่เรียกว่าAspectและคุณจะเขียนคลาส:

@Aspect
public class MyAwesomeAspect{....}

เพื่อให้สิ่งเหล่านี้ทำงานได้ผลคุณจะต้องบอกให้ Spring แยกวิเคราะห์ชั้นเรียนเพื่ออ่านทำความเข้าใจและดำเนินการกับคำหลัก @ AOP วิธีหนึ่งที่ทำได้คือระบุสิ่งต่อไปนี้ในไฟล์ spring config xml:

<aop:aspectj-autoproxy>


1
ฉันยังใหม่กับ AOP และคำอธิบายนี้ช่วยให้ฉันเข้าใจความสัมพันธ์ระหว่าง Advice / Pointcuts / JoinPoints ได้ค่อนข้างชัดเจน
Jatin Shashoo

นี่เป็นคำอธิบายที่ดีกว่าสำหรับมือใหม่ ขอบคุณ
Aakash

11

การเปรียบเทียบภาษา AOP เช่น AspectJ กับภาษาคิวรีข้อมูลเช่น SQL คุณสามารถนึกถึงจุดเชื่อมต่อ (เช่นตำแหน่งทั้งหมดในโค้ดของคุณที่คุณสามารถสานโค้ดด้าน) เป็นตารางฐานข้อมูลที่มีหลายแถว พอยต์คัตเปรียบเสมือนการสแตมเมนต์ SELECT ซึ่งสามารถเลือกเซ็ตย่อยของแถว / จุดเชื่อมที่ผู้ใช้กำหนดเองได้ รหัสจริงที่คุณรวมไว้ในสถานที่ที่เลือกเหล่านั้นเรียกว่าคำแนะนำ


9

คำจำกัดความ

ตามเอกสาร:

จุดเข้าร่วม:จุดระหว่างการดำเนินการของโปรแกรมเช่นการดำเนินการของวิธีการหรือการจัดการข้อยกเว้น

คุณสามารถพิจารณาจุดร่วมเป็นเหตุการณ์ในการทำงานของโปรแกรม หากคุณใช้ Spring AOP สิ่งนี้จะ จำกัด เฉพาะการเรียกใช้วิธีการ AspectJ ให้ความยืดหยุ่นมากขึ้น

แต่คุณไม่เคยจัดการกับเหตุการณ์ทั้งหมดเนื่องจากคุณไม่ได้กินอาหารทั้งหมดในเมนูเมื่อคุณไปที่ร้านอาหาร (ฉันไม่รู้จักคุณคุณอาจจะ! แต่ฉันไม่ทำอย่างแน่นอน) ดังนั้นคุณจึงเลือกเหตุการณ์ที่จะจัดการและจะทำอย่างไรกับเหตุการณ์เหล่านั้น ที่นี่จะไปPointcuts ตามเอกสารประกอบ

Pointcut : เพรดิเคตที่ตรงกับจุดรวม

แล้วคุณจะเชื่อมโยงสิ่งที่จะทำอย่างไรกับpointcutมีไปแนะนำ ตามเอกสารประกอบ

แนะนำมีความเกี่ยวข้องกับpointcutแสดงออกและวิ่งไปที่จุดใด ๆ เข้าร่วมการจับคู่โดย 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
    }

}

คำอธิบายรหัส

  • ExampleBusinessClass เมื่อ proxy-ed เป็นเป้าหมายของเรา!
  • doYourBusiness()เป็นจุดร่วมที่เป็นไปได้
  • SomeAspect เป็นแง่มุมของเราที่ข้ามไปสู่ความกังวลหลายประการเช่นนี้ ExampleBusinessClass
  • somePointCut()คือคำจำกัดความของจุดตัดที่ตรงกับจุดร่วมของเรา
  • afterSomePointCut()เป็นคำแนะนำที่จะดำเนินการหลังจากการsomePointCut ตัดแต้มของเราที่ตรงกับdoYourBusiness() จุดร่วม
  • beforeSomePointCut()ยังเป็นคำแนะนำที่ตรงกับpublicวิธีการดำเนินการทั้งหมด ต่างจากafterSomePointCutนี้ใช้การประกาศจุดตัดแบบอินไลน์

คุณสามารถดูเอกสารถ้าคุณไม่เชื่อฉัน ฉันหวังว่านี่จะช่วยได้


1
คำอธิบายง่ายๆ ข้อความที่ยกมาเพียงสามข้อก็เพียงพอที่จะเข้าใจ ขอบคุณ.
TRiNE

6

ทั้งสองอย่างเกี่ยวข้องกับ "ที่ไหน" ของการเขียนโปรแกรมเชิงมุมมอง

จุดเชื่อมต่อคือสถานที่แต่ละแห่งที่คุณสามารถรันโค้ดด้วย AOP เช่น "เมื่อเมธอดแสดงข้อยกเว้น"

พอยต์คัทคือการรวบรวมคะแนนเข้าร่วม เช่น "เมื่อเมธอดในคลาส Foo แสดงข้อยกเว้น"


5

JoinPoint : Joinpoint คือจุดในการดำเนินการโปรแกรมของคุณซึ่งมีการเปลี่ยนแปลงขั้นตอนการดำเนินการเช่นการจับข้อยกเว้นการเรียกใช้วิธีอื่น

PointCut : PointCut เป็นจุดเชื่อมต่อที่คุณสามารถให้คำแนะนำ (หรือด้านการโทร)

ดังนั้นโดยทั่วไปPointCuts เป็นส่วนย่อยของ JoinPoints


3

AOP ในฤดูใบไม้ผลิมี {Advisor, Advice, Pointcut, Joinpoint}

ดังที่คุณทราบจุดประสงค์หลักของ aop คือการแยกตรรกะเกี่ยวกับการตัดขวาง (Aspect) ออกจากรหัสแอปพลิเคชันเพื่อนำสิ่งนี้ไปใช้ในฤดูใบไม้ผลิเราใช้ (คำแนะนำ / ที่ปรึกษา)

Pointcut ใช้เพื่อกรองตำแหน่งที่เราต้องการใช้คำแนะนำนี้เช่น "วิธีการทั้งหมดเริ่มต้นด้วยการแทรก" ดังนั้นวิธีอื่น ๆ จะถูกยกเว้นนั่นคือเหตุผลที่เรามีในอินเทอร์เฟซ Pointcut {ClassFilter and MethodMatcher}

ดังนั้น Advice คือการใช้งานลอจิกแบบ cross-cutting และ Advisor คือคำแนะนำพร้อม PointCut หากคุณใช้เพียงคำแนะนำสปริงจะแมปให้ที่ปรึกษาและทำให้ pointcut เป็น TRUE ซึ่งหมายความว่าอย่าปิดกั้นอะไรเลย นั่นเป็นเหตุผลว่าทำไมเมื่อคุณใช้คำแนะนำเพียงอย่างเดียวระบบจะนำไปใช้กับวิธีการทั้งหมดของคลาสเป้าหมายเนื่องจากคุณไม่ได้กรอง

แต่ Joinpoint เป็นตำแหน่งในโปรแกรมคุณสามารถคิดว่ามันเหมือนกับการสะท้อนเมื่อคุณเข้าถึงวัตถุคลาสจากนั้นคุณจะได้รับวัตถุ Method จากนั้นคุณสามารถเรียกใช้เมธอดใดก็ได้ในคลาสนี้และนั่นคือวิธีการทำงานของคอมไพเลอร์หากคุณคิดเช่นนั้น สิ่งนี้คุณสามารถจินตนาการถึงจุดเข้าร่วม

Joinpoint สามารถอยู่กับฟิลด์ตัวสร้างหรือวิธีการ แต่ในฤดูใบไม้ผลิเรามีจุดเชื่อมต่อกับเมธอดเท่านั้นนั่นเป็นเหตุผลว่าทำไมในฤดูใบไม้ผลิเราจึงมีประเภท Joinpoint (Before, After, Throws, Around) ทั้งหมดนี้หมายถึงตำแหน่งในคลาส

ดังที่ได้กล่าวไปว่าคุณสามารถมีคำแนะนำได้โดยไม่ต้องใช้ pointcut (ไม่มีตัวกรอง) จากนั้นจะนำไปใช้กับทุกวิธีหรือคุณสามารถมีที่ปรึกษาซึ่งเป็น [คำแนะนำ + pointcut] ซึ่งจะนำไปใช้กับวิธีการเฉพาะ แต่คุณไม่สามารถให้คำแนะนำได้หากไม่มี จุดเชื่อมเช่น pointcut คุณต้องระบุและนั่นคือเหตุผลที่ประเภทคำแนะนำในฤดูใบไม้ผลิเป็นประเภทเดียวกับจุดเชื่อมต่อดังนั้นเมื่อคุณเลือกคำแนะนำคุณจะเลือกจุดเชื่อมโดยปริยาย

ในการสรุปคำแนะนำคือตรรกะในการใช้งานสำหรับมุมมองของคุณกับคลาสเป้าหมายคำแนะนำนี้ควรมีจุดเชื่อมต่อเช่นก่อนการเรียกใช้หลังการเรียกใช้หลังจากการขว้างปาหรือการเรียกใช้จากนั้นคุณสามารถกรองตำแหน่งที่คุณต้องการใช้โดยใช้ pointcut เพื่อ กรอง method หรือ no pointcut (ไม่มีตัวกรอง) ดังนั้นจะถูกนำไปใช้กับ method ทั้งหมดของ class


3

Pointcut ถูกกำหนดไว้ในการนำ Aspect - class ไปใช้งาน จุดตัดโดยทั่วไปหมายถึงการแสดงออกของคำแนะนำในคำแนะนำ

สำหรับเช่น

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

วิธีการข้างต้นเรียกเมธอด "includeAddOns" ก่อนที่จะเรียกใช้ (เนื่องจากคำแนะนำ @Before) เมธอดใด ๆ (ในคลาสภายในแพ็คเกจ "app.purchase2.service.impl")

คำอธิบายประกอบทั้งหมดเรียกว่า pointcut @Before("execution(* app.purchase2.service.impl.*(..))")

จุดร่วมคือการเรียกใช้เมธอดจริงซึ่งรวมเมธอดในแพ็กเกจ "app.purchase2.service.impl" เข้ากับเมธอดในคลาสด้าน "includeAddOns ()"

คุณสามารถเข้าถึงคุณสมบัติของจุดเข้าร่วมกับorg.aspectj.lang.JoinPointชั้นเรียน


คำตอบที่ดี! ในที่สุดฉันก็เข้าใจความแตกต่าง!
Dante

2

ฉันเห็นด้วยกับ mgroves .. การตัดแต้มถือได้ว่าเป็นการรวบรวมจุดร่วมหลาย ๆ จุด จุดร่วมระบุตำแหน่งเฉพาะที่สามารถนำคำแนะนำไปใช้โดยที่ pointcut สะท้อนรายการจุดร่วมทั้งหมด


0

JoinPoint:ระบุจุด (วิธีการ) ในแอปพลิเคชันที่จะดำเนินการ Advice

Pointcut:เป็นการรวมกันของ JoinPoints และระบุว่าจะดำเนินการที่ JoinPoint Advice


-5

จุดเข้าร่วมคือสถานที่ที่เราให้คำปรึกษาจริงๆ

แต่จุดตัดคือการรวบรวมคะแนนเข้าร่วม นั่นหมายถึงว่าเราวางตรรกะการตัดขวางกี่วิธีที่เรียกว่าจุดตัด

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.