Spring AOP: Jaka jest różnica między JoinPoint a PointCut?


88

Uczę się koncepcji programowania zorientowanego na aspekty i Spring AOP. Nie rozumiem różnicy między Pointcut a Joinpoint - oba wydają mi się takie same. Pointcut to miejsce, w którym stosujesz się do porad, a Joinpoint to także miejsce, w którym możemy skorzystać z naszych porad. Więc jaka jest różnica?

Przykładem punktu przekroju może być:

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

Co może być przykładem Joinpointa?

Odpowiedzi:


161

Punkt złączenia: punkt złączenia to punkt kandydujący w wykonaniu programu aplikacji, do którego można podłączyć aspekt. Punktem tym może być wywołanie metody, zgłoszenie wyjątku lub nawet modyfikacja pola. Są to punkty, w których kod aspektu można wstawić do normalnego przepływu aplikacji, aby dodać nowe zachowanie.

Porada: Jest to obiekt, który zawiera wywołania API związane z ogólnosystemowymi problemami reprezentującymi akcję wykonywaną w punkcie złączenia określonym przez punkt.

Punkt przecięcia: Punkt przecięcia określa, w których punktach połączenia należy zastosować odpowiednią radę. Porady można zastosować w dowolnym punkcie przyłączenia obsługiwanym przez platformę AOP. Oczywiście nie chcesz stosować wszystkich swoich aspektów we wszystkich możliwych punktach złączenia. Pointcuts pozwalają określić, gdzie chcesz zastosować twoją radę. Często określa się te punkty za pomocą jawnych nazw klas i metod lub za pomocą wyrażeń regularnych, które definiują pasujące wzorce nazw klas i metod. Niektóre struktury AOP umożliwiają tworzenie dynamicznych wskaźników, które określają, czy zastosować porady na podstawie decyzji w czasie wykonywania, takich jak wartość parametrów metody.

Poniższy obraz może pomóc w zrozumieniu porad, PointCut, Joinpoints. wprowadź opis obrazu tutaj

Źródło

Wyjaśnienie na podstawie analogii restauracji: źródło: @Victor

Kiedy wychodzisz do restauracji, patrzysz na menu i widzisz kilka opcji do wyboru. Możesz zamówić jedną lub więcej pozycji w menu. Ale dopóki ich nie zamówisz, są tylko „okazją do obiadu”. Kiedy złożysz zamówienie, a kelner wniesie je do stolika, jest to posiłek.

Punkty łączenia to opcje w menu, a skróty to elementy, które wybierasz.

Joinpoint to szansa w kodzie na zastosowanie aspektu ... po prostu szansa. Gdy skorzystasz z tej okazji i wybierzesz jeden lub więcej punktów złączenia i zastosujesz do nich aspekt, otrzymasz punkt przecięcia.

Źródło Wiki :

Punkt złączenia to punkt w przepływie sterowania programu, w którym przepływ sterowania może dotrzeć dwiema różnymi ścieżkami (IMO: dlatego nazywamy połączenie).

Porada opisuje klasę funkcji, które modyfikują inne funkcje

Punkt przecięcia to zbiór punktów połączenia.


3
Powinno to być oznaczone jako poprawna odpowiedź. Aby dodać więcej informacji, spójrz na odpowiedź Cragi Walls ... coderanch.com/t/485525/Spring/Difference-Joint-Point-Point-Cut .
Victor

2
Do rzeczy: punkt przecięcia określa, w jakich punktach złączenia rada powinna być zastosowana +1
Gala Naman

Tylko dla potwierdzenia, more Joinpoints and apply an aspect to them, you've got a Pointcut. aspektu lub porady dla nich?
Asif Mushtaq

@Premraj A więc zgodnie z twoją analogią rada będzie zamawianie posiłku. Czy mam rację?
Vishwas Atrey

Analogia do restauracji pomogła w wyjaśnieniu nieporozumień między punktami JoinPoints a punktami. Dzięki!
SM

30

Aby zrozumieć różnicę między punktem połączenia a punktem połączenia, należy pomyśleć o punktach jako określających zasady tkania, a punkty złączenia jako o sytuacjach spełniających te zasady.

W poniższym przykładzie

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

Pointcut definiuje reguły mówiące, że rady powinny być stosowane do metody getName () obecnej w dowolnej klasie w dowolnym pakiecie, a joinpoints będzie listą wszystkich metod getName () obecnych w klasach, aby można było zastosować porady dotyczące tych metod.

(W przypadku wiosny reguła zostanie zastosowana tylko do zarządzanej fasoli, a porady można zastosować tylko do metod publicznych).


1
„Pointcut definiuje reguły mówiące, że porady powinny być stosowane do metody getName () obecnej w dowolnej klasie w dowolnym pakiecie, a punkty złączenia będą listą wszystkich metod getName () obecnych w klasach, aby można było zastosować porady dotyczące tych metod”. Przepraszam, ale to staje się coraz bardziej zagmatwane. Czy możesz podać mi analogię w scenariuszu z codziennego życia?
Saurabh Patil

28

JoinPoints: Są to w zasadzie miejsca w rzeczywistej logice biznesowej, w których chcesz wstawić różne dodatkowe funkcje, które są konieczne, ale nie są częścią rzeczywistej logiki biznesowej. Niektóre przykłady JoinPint to: wywołanie metody, metoda zwracająca normalnie, metoda zgłaszająca wyjątek, tworzenie instancji obiektu, odwoływanie się do obiektu itp.

Pointcuts: Pointcuts to coś w rodzaju wyrażeń regularnych, które są używane do identyfikacji punktów złączenia. Podcięcia są wyrażane za pomocą „języka wyrażeń punktowych”. Punkty przecięcia to punkty przepływu wykonywania, w których należy zastosować problem przekrojowy. Istnieje różnica między Joinpoint a Pointcut; Punkty złączenia są bardziej ogólne i reprezentują każdy przepływ kontroli, w którym „możemy zdecydować się” wprowadzić problem przekrojowy, podczas gdy punkt przecięcia identyfikuje takie punkty złączenia, w których „chcemy” wprowadzić problem przekrojowy.


1
Joinpoint - Potencjalne miejsca do zastosowania / uruchomienia kodu porady. Pointcut - aktualnie wybrane punkty złączenia do wykonania porady.
user104309

26

Wyjaśnienie laika dla kogoś, kto jest nowy w pojęciach AOP. To nie jest wyczerpujące, ale powinno pomóc w zrozumieniu pojęć. Jeśli znasz już podstawowy żargon, możesz przestać czytać.

Załóżmy, że masz normalną klasę Employee i chcesz coś zrobić za każdym razem, gdy wywoływane są te metody.

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

metody te nazywane są JoinPoints . Potrzebujemy sposobu na zidentyfikowanie tych metod, aby framework mógł znaleźć metody wśród wszystkich załadowanych klas. Metod. Dlatego napiszemy wyrażenie regularne pasujące do sygnatury tych metod. Chociaż jest w tym coś więcej, jak zobaczysz poniżej, ale luźno to wyrażenie regularne jest tym, co definiuje Pointcut . na przykład

* * mypackage.Employee.get*(*)

Pierwszy * oznacza modyfikator public / private / protected / default. Druga * służy do zwracania typu metody.

Ale musisz też powiedzieć jeszcze dwie rzeczy:

  1. Kiedy należy podjąć akcję - np. Przed / Po wykonaniu metody LUB w przypadku wyjątku
  2. Co powinien zrobić, gdy pasuje (może po prostu wydrukuj wiadomość)

Połączenie tych dwóch nazywa się radą .

Jak możesz sobie wyobrazić, musiałbyś napisać funkcję, aby móc wykonać # 2. Więc tak to może wyglądać w przypadku podstaw.

Uwaga: dla jasności użyj słowa REGEX zamiast * * mypackage.Employee.get*(*). W rzeczywistości do definicji dochodzi pełne wyrażenie.

@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

Kiedy zaczniesz ich używać, możesz skończyć z określeniem wielu porad @ After / @ Before / @ Around. Te powtarzające się wyrażenia regularne będzie ostatecznie skończyć tworzenie rzeczy kłopotliwe i trudne do utrzymania. Więc co robimy, po prostu nadajemy nazwę wyrażeniu i używamy go wszędzie indziej w klasie 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() {....}

Przy okazji, chciałbyś również opakować całą tę logikę w klasę, która nazywa się Aspect, i napisałbyś klasę:

@Aspect
public class MyAwesomeAspect{....}

Aby wszystkie te rzeczy działały, musiałbyś powiedzieć Springowi, aby przeanalizował klasy, aby przeczytały, zrozumiały i podjęły działania na słowach kluczowych @ AOP. Jednym ze sposobów jest określenie następujących elementów w pliku XML config wiosny:

<aop:aspectj-autoproxy>


1
Jestem nowy w AOP i to wyjaśnienie pomogło mi dość wyraźnie zrozumieć związek między poradami / punktami / połączeniami.
Jatin Shashoo,

To, proszę pana, znacznie lepsze wyjaśnienie dla nowicjusza. Dziękuję
Aakash

11

Porównując język AOP, taki jak AspectJ, z językiem zapytań o dane, takim jak SQL, możesz myśleć o punktach złączenia (tj. Wszystkich miejscach w kodzie, w których można wplatać kod aspektu) jako o tabeli bazy danych z wieloma wierszami. Punkt przecięcia jest jak pręcik SELECT, który może wybrać podzbiór wierszy / punktów łączenia zdefiniowany przez użytkownika. Rzeczywisty kod, który wplatasz w wybrane miejsca, to porada.


9

Definicje

Zgodnie z dokumentacją:

Punkt połączenia: punkt podczas wykonywania programu, taki jak wykonanie metody lub obsługa wyjątku.

Punkty wspólne można traktować jako wydarzenia w trakcie wykonywania programu. Jeśli używasz Spring AOP, jest to nawet ograniczone do wywoływania metod. AspectJ zapewnia większą elastyczność.

Ale nigdy nie radzisz sobie ze wszystkimi wydarzeniami, ponieważ nie jesz całego jedzenia z menu, gdy idziesz do restauracji (nie znam cię, możesz! Ale na pewno nie). Dokonujesz więc wyboru zdarzeń, które chcesz obsłużyć i co z nimi zrobić. Tutaj idzie Pointcuts . Zgodnie z dokumentacją

Pointcut : predykat pasujący do punktów złączenia .

Następnie kojarzysz co zrobić z Pointcutem , tam idzie Porada . Zgodnie z dokumentacją

Porada jest powiązana z wyrażeniem punktu przecięcia i jest uruchamiana w dowolnym punkcie połączenia dopasowanym do punktu przecięcia.

Kod

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
    }

}

Wyjaśnienie kodu

  • ExampleBusinessClass kiedy proxy jest naszym celem!
  • doYourBusiness()to możliwy wspólny punkt
  • SomeAspect to nasz aspekt, który krzyżuje się z wieloma problemami, takimi jak tyłek ExampleBusinessClass
  • somePointCut()to definicja przecięcia punktowego, która pasuje do naszego wspólnego punktu
  • afterSomePointCut()to rada, która zostanie wykonana po naszym somePointCut cięciu punktowym , pasującym do doYourBusiness() wspólnego punktu
  • beforeSomePointCut()jest również wskazówką pasującą do wszystkich publicwykonań metod. W przeciwieństwie do afterSomePointCuttego używa deklaracji cięcia punktowego w wierszu

Możesz zajrzeć do dokumentacji, jeśli mi nie wierzysz. mam nadzieję, że to pomoże


1
Proste wyjaśnienie. Do zrozumienia wystarczą tylko trzy cytowane teksty. Dzięki.
TRiNE

6

Oba odnoszą się do „gdzie” programowania aspektowego.

Punkt złączenia to indywidualne miejsce, w którym można wykonać kod za pomocą AOP. Np. „Kiedy metoda zgłasza wyjątek”.

Punkt przecięcia to zbiór punktów połączenia. Np. „Gdy metoda z klasy Foo zgłasza wyjątek”.


4

JoinPoint : JoinPoint to punkty w wykonywaniu programu, w których przepływ wykonywania został zmieniony, jak przechwytywanie wyjątków, wywoływanie innej metody.

PointCut : PointCut to w zasadzie te punkty łączenia, w których możesz umieścić swoją radę (lub aspekt połączenia).

Więc w zasadzie PointCuts są podzbiorem JoinPoints .


3

AOP wiosną ma {Advisor, Advice, Pointcut, Joinpoint}

Jak wiecie, głównym celem aop jest oddzielenie logiki przekrojowych problemów (Aspekt) od kodu aplikacji, aby wdrożyć to wiosną, używamy (Advice / Advisor)

Pointcut jest używany do filtrowania tam, gdzie chcemy dokładnie zastosować tę radę, na przykład „wszystkie metody zaczynają się od wstawienia”, więc inne metody zostaną wykluczone, dlatego w interfejsie Pointcut mamy {ClassFilter i MethodMatcher}

Tak więc Porada jest implementacją logiki przekrojowej, a Doradca to rada plus PointCut, jeśli używasz tylko porad, sprężyna mapuje ją do doradcy i sprawi, że punkt przecięcia będzie PRAWDA, co oznacza, że ​​niczego nie blokuj. Dlatego gdy używasz tylko rady, jest ona stosowana do wszystkich metod klasy docelowej, ponieważ ich nie filtrowałeś.

Ale Joinpoint jest lokalizacją w programie, możesz myśleć o tym jak o odbiciu, kiedy uzyskujesz dostęp do obiektu Class, a następnie możesz uzyskać obiekt Method, następnie możesz wywołać dowolną metodę w tej klasie i tak działa kompilator, jeśli myślisz, że to możesz sobie wyobrazić Joinpoint.

Joinpoint może być z polem, konstruktorem lub metodą, ale w Spring mamy joinpoint tylko z metodami, dlatego w Spring mamy typy Joinpoint (Before, After, Throws, Around), wszystkie odnoszą się do lokalizacji w klasie.

Jak wspomniałem, możesz mieć radę bez punktowania (bez filtra), wtedy będzie ona stosowana do wszystkich metod lub możesz mieć doradcę, którym jest [rada + punkt], który będzie stosowany do określonych metod, ale nie możesz mieć rady bez joinpoint jak pointcut, musisz je określić i dlatego typy porad na wiosnę są dokładnie takie same jak joinpoint, więc kiedy wybierasz poradę, niejawnie wybierasz, który punkt złączenia.

Podsumowując, rada jest logiką implementacji twojego aspektu do klasy docelowej, ta rada powinna mieć punkt sprzężenia, taki jak przed wywołaniem, po wywołaniu, po wyrzuceniu lub wokół wywołania, wtedy możesz filtrować, gdzie dokładnie chcesz go zastosować za pomocą pointcut do filtruj metody lub bez punktu cięcia (bez filtra), więc zostanie zastosowany do wszystkich metod klasy.


3

Punkt przekroju jest definiowany w implementacji klasy Aspect. Punkt cięcia zasadniczo odnosi się do wyrażenia punktowego w poradie.

Np.

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

Powyższe oznacza, że ​​metoda „includeAddOns” jest wywoływana przed wywołaniem (z powodu porady @Before) jakichkolwiek metod (w klasach w pakiecie „app.purchase2.service.impl”)

Cały opis nazywany jest punktem przecięcia @Before("execution(* app.purchase2.service.impl.*(..))")

Punktem wspólnym jest faktyczne wywołanie metody, która połączyła metodę z pakietu „app.purchase2.service.impl” z metodą w klasie aspektu „includeAddOns ()”.

Możesz uzyskać dostęp do właściwości punktu łączenia z org.aspectj.lang.JoinPointklasą.


Dobra odpowiedź! W końcu zrozumiałem różnicę!
Dante

2

Zgadzam się z mgroves .. Cięcie punktowe można traktować jako zbiór wielu wspólnych punktów. Wspólny punkt określa konkretną lokalizację, w której może zostać wdrożona porada, gdzie jako punkt przekroju odzwierciedla listę wszystkich połączonych punktów.


0

JoinPoint: określa punkt (metodę) w aplikacji, w którym zostanie wykonana Rada.

Pointcut: Jest to kombinacja JoinPoints i określa, w jakim punkcie JoinPoint Advice będą wykonywane.


-5

punkt przyłączenia to miejsce, w którym faktycznie umieszczamy porady

ale cięcie punktowe to zbiór punktów złączenia. Oznacza to, na ile sposobów możemy umieścić logikę przecinania nazywaną cięciem punktowym

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.