Spring AOP: в чем разница между JoinPoint и PointCut?


88

Я изучаю концепции аспектно-ориентированного программирования и Spring AOP. Я не понимаю разницы между Pointcut и Joinpoint - оба они кажутся мне одинаковыми. Pointcut - это то место, где вы применяете свой совет, а Joinpoint - это также место, где мы можем применить наш совет. Тогда какая разница?

Примером pointcut может быть:

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

Что может быть примером точки соединения?

Ответы:


161

Точка соединения: точка соединения - это точка- кандидат в выполнении программы приложения, в которую может быть включен аспект. Эта точка может быть вызываемым методом, генерируемым исключением или даже изменяемым полем. Это точки, в которых код вашего аспекта может быть вставлен в нормальный поток вашего приложения для добавления нового поведения.

Совет: это объект, который включает вызовы API для общесистемных проблем, представляющих действие, выполняемое в точке соединения, указанной точкой.

Pointcut: pointcut определяет, в каких точках соединения следует применить соответствующий совет. Совет может применяться в любой точке соединения, поддерживаемой платформой АОП. Конечно, вы не хотите применять все свои аспекты во всех возможных точках соединения. Pointcuts позволяет вам указать, где вы хотите, чтобы ваш совет был применен. Часто вы указываете эти точки с помощью явных имен классов и методов или с помощью регулярных выражений, которые определяют соответствующие шаблоны имен классов и методов. Некоторые фреймворки АОП позволяют создавать динамические точки, которые определяют, применять ли совет на основе решений времени выполнения, таких как значение параметров метода.

Следующее изображение может помочь вам понять Advice, PointCut, Joinpoints. введите описание изображения здесь

Источник

Объяснение с использованием аналогии с рестораном: Источник от @Victor

Когда вы идете в ресторан, вы просматриваете меню и видите несколько вариантов на выбор. Вы можете заказать один или несколько пунктов меню. Но пока вы их не закажете, это просто «возможность пообедать». Как только вы разместите заказ, и официант принесет его к вашему столу, это будет еда.

Точки соединения - это опции в меню, а Pointcut - это элементы, которые вы выбираете.

Точка соединения - это возможность в коде для вас применить аспект ... просто возможность. Как только вы воспользуетесь этой возможностью, выберете одну или несколько точек соединения и примените к ним аспект, вы получите Pointcut.

Исходная вики :

Точка соединения - это точка в потоке управления программы, куда поток управления может поступать двумя разными путями. (IMO: вот почему вызывается соединение).

Совет описывает класс функций, которые изменяют другие функции.

Срез точки представляет собой набор точек соединения.


3
Это должно быть отмечено как правильный ответ. Чтобы добавить больше информации, посмотрите ответ Cragi Walls ... 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. аспекта для них или совета для них?
Асиф Муштак

@Premraj Итак, по вашей аналогии совет будет заказывать еду. Я прав?
Вишвас Атри 01

Аналогия с рестораном помогла устранить путаницу между JoinPoints и pointcuts, спасибо!
SM

30

Чтобы понять разницу между точкой соединения и pointcut, представьте, что pointcut задает правила плетения, а точки соединения - как ситуации, удовлетворяющие этим правилам.

В приведенном ниже примере

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

Pointcut определяет правила, в которых говорится, что совет должен применяться к методу getName (), присутствующему в любом классе в любом пакете, а точки соединения будут списком всех методов getName (), присутствующих в классах, чтобы совет можно было применить к этим методам.

(В случае Spring, правило будет применяться только к управляемым bean-компонентам, а рекомендации могут применяться только к общедоступным методам).


1
«Pointcut определяет правила, говорящие, что совет должен применяться к методу getName (), присутствующему в любом классе в любом пакете, а точки соединения будут списком всех методов getName (), присутствующих в классах, так что совет может быть применен к этим методам». Извините, но это сбивает с толку. Не могли бы вы провести аналогию с реальным сценарием повседневной жизни?
Саураб Патил

28

JoinPoints: это в основном места в реальной бизнес-логике, куда вы хотите вставить некоторые разные функции, которые необходимы, но не являются частью реальной бизнес-логики. Вот некоторые примеры JoinPints: вызов метода, обычный возврат метода, метод, генерирующий исключение, создание экземпляра объекта, ссылка на объект и т. Д.

Pointcuts: Pointcuts - это что-то вроде регулярных выражений, которые используются для идентификации точек соединения. Pontcuts выражаются с помощью "языка выражения pointcut". Pointcuts - это точки потока выполнения, к которым необходимо применить сквозную заботу. Есть разница между Joinpoint и Pointcut; Точки соединения являются более общими и представляют собой любой поток управления, в котором мы «можем выбрать» ввести сквозную проблему, в то время как pointcuts идентифицирует такие точки соединения, в которых «мы хотим» ввести сквозную проблему.


1
Точка соединения - потенциальные места для применения / запуска кода рекомендации. Pointcut - фактически выбранные точки соединения для выполнения совета.
user104309

26

Объяснение непрофессионала для тех, кто плохо знаком с концепциями АОП. Это не является исчерпывающим, но должно помочь в понимании концепций. Если вы уже знакомы с основным жаргоном, можете перестать читать.

Предположим, у вас есть обычный класс Employee, и вы хотите что-то делать каждый раз при вызове этих методов.

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

эти методы называются JoinPoints . Нам нужен способ идентифицировать эти методы, чтобы фреймворк мог найти методы среди всех загруженных классов. Итак, мы напишем регулярное выражение, соответствующее сигнатуре этих методов. Хотя это еще не все, как вы увидите ниже, но в общих чертах это регулярное выражение определяет Pointcut . например

* * mypackage.Employee.get*(*)

Первый * предназначен для модификатора 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() {....}

Кстати, вы также можете обернуть всю эту логику в класс, который называется Aspect, и вы бы написали класс:

@Aspect
public class MyAwesomeAspect{....}

Чтобы все это заработало, вам нужно будет указать Spring проанализировать классы, чтобы прочитать, понять ключевые слова @ AOP и предпринять соответствующие действия. Один из способов сделать это - указать в XML-файле конфигурации spring следующее:

<aop:aspectj-autoproxy>


1
Я новичок в АОП, и это объяснение помогло мне довольно четко понять взаимосвязь между Advice / Pointcuts / JoinPoints.
Jatin Shashoo

Это, сэр, гораздо лучшее объяснение для новичка. Спасибо
Аакаш

11

Сравнивая язык АОП, такой как AspectJ, с языком запросов данных, таким как SQL, вы можете представить себе точки соединения (то есть все места в вашем коде, где вы можете вплетать аспектный код) как таблицу базы данных с множеством строк. Pointcut похож на SELECT stamement, который может выбирать определяемое пользователем подмножество строк / точек соединения. Фактический код, который вы вплетаете в эти выбранные места, называется советом.


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 когда прокси-сервер является нашей целью!
  • doYourBusiness()это возможная точка соединения
  • SomeAspect это наш аспект, который пересекается с множеством проблем, таких как задница ExampleBusinessClass
  • somePointCut()это определение точечного разреза, которое соответствует нашей точке соединения
  • afterSomePointCut()это совет, который будет выполнен после того, как наша somePointCut точка разреза соответствует doYourBusiness() точке соединения
  • beforeSomePointCut()также совет, который подходит для всех publicвыполнений методов. В отличие от afterSomePointCutэтого, здесь используется объявление встроенной точки.

Вы можете посмотреть документацию, если мне не верите. надеюсь, это поможет


1
Простое объяснение. Для понимания достаточно всего трех цитируемых текстов. Спасибо.
TRiNE

6

Оба относятся к «где» аспектно-ориентированного программирования.

Точка соединения - это отдельное место, где вы можете выполнять код с помощью АОП. Например, «когда метод вызывает исключение».

Pointcut - это набор точек соединения. Например, «когда метод в классе Foo выдает исключение».


4

JoinPoint : Joinpoint - это точки в выполнении вашей программы, где поток выполнения был изменен, например, перехват исключений, вызов другого метода.

PointCut : PointCut - это в основном те точки соединения, в которые вы можете поместить свой совет (или вызвать аспект).

Таким образом, PointCuts - это подмножество JoinPoints .


3

Весной в АОП есть {Advisor, Advice, Pointcut, Joinpoint}

Как вы знаете, основная цель aop - отделить сквозную логику (Aspect) от кода приложения, чтобы реализовать это в Spring, которую мы используем (Advice / Advisor)

Pointcut используется для фильтрации того места, где мы хотим точно применить этот совет, например, «все методы начинаются со вставки», поэтому другие методы будут исключены, поэтому у нас в интерфейсе Pointcut есть {ClassFilter и MethodMatcher}

Итак, Advice - это реализация сквозной логики, а Advisor - это совет плюс PointCut, если вы используете только совет, Spring сопоставит его с советником и установит pointcut в ИСТИНА, что означает, что ничего не блокирует. Вот почему, когда вы используете только совет, он применяется ко всем методам целевого класса, потому что вы их не фильтровали.

Но Joinpoint - это место в программе, вы можете думать об этом как об отражении, когда вы обращаетесь к объекту Class, а затем вы можете получить объект Method, затем вы можете вызвать любой метод в этом классе, и то, как работает компилятор, если вы думаете, что вы можете себе представить точку соединения.

Точка соединения может быть с полем, конструктором или методом, но в Spring у нас есть точка соединения только с методами, поэтому в Spring у нас есть типы точки соединения (до, после, бросания, вокруг), все они относятся к местоположениям в классе.

Как я уже упоминал, у вас может быть совет без pointcut (без фильтра), тогда он будет применяться ко всем методам, или у вас может быть советник, который будет [advice + pointcut], который будет применяться к определенным методам, но у вас не может быть совета без точка соединения, такая как pointcut, вы должны указать ее, и поэтому типы рекомендаций в Spring точно такие же, как и точки соединения, поэтому, когда вы выбираете совет, вы неявно выбираете, какая точка соединения.

Подводя итог, совет - это логика реализации вашего аспекта целевого класса, этот совет должен иметь точку соединения, как перед вызовом, после вызова, после выброса или вокруг вызова, тогда вы можете отфильтровать, где именно вы хотите применить его, используя pointcut to отфильтровать методы или без pointcut (без фильтра), чтобы он применялся ко всем методам класса.


3

Pointcut определяется в реализации класса Aspect. Точечный разрез в основном относится к выражению pointcut в рекомендации.

Например,

@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классом.


Хороший ответ! Наконец-то я понял разницу!
Данте

2

Я согласен с mgroves .. Точечный разрез можно рассматривать как совокупность нескольких точек соединения. Точка соединения указывает конкретное место, где может быть реализована рекомендация, где as pointcut отражает список всех точек соединения.


0

JoinPoint: указывает точку (метод) в приложении, где будет выполняться Advice.

Pointcut: это комбинация JoinPoints, и она указывает, на каком совете JoinPoint будет выполняться.


-5

точка соединения - это место, где мы размещаем советы

но точечный разрез - это совокупность точек соединения. это означает, что то, сколько способов мы используем сквозную логику, называется точечным разрезом.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.