Spring AOP:JoinPoint和PointCut有什么区别?


88

我正在学习面向方面的编程概念和Spring AOP。我无法理解切入点和连接点之间的区别-对我来说,两者似乎是相同的。Pointcut是您应用建议的地方,Joinpoint也是我们可以应用建议的地方。那有什么区别呢?

切入点的示例可以是:

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

联接点的示例可以是什么?

Answers:


161

连接点连接点是应用程序的程序执行中可以插入方面的候选点。此点可以是调用方法,引发异常或甚至修改字段。这些是您的方面的代码可以插入到应用程序的常规流程中以添加新行为的要点。

忠告:这是一个对象,其中包括对系统范围内关注点的API调用,这些关注点表示要在点指定的连接点处执行的操作。

切入点:切入点定义了应在哪些连接点处应用关联的建议。可以在AOP框架支持的任何连接点上应用建议。当然,您不想在所有可能的连接点上应用所有方面。切入点允许您指定要在何处应用建议。通常,您使用显式的类和方法名称或通过定义匹配的类和方法名称模式的正则表达式来指定这些切入点。某些AOP框架允许您创建动态切入点,这些切入点可根据运行时决策(例如方法参数的值)确定是否应用建议。

下图可以帮助您了解建议,PointCut,Joinpoints。 在此处输入图片说明

资源

使用餐厅类比的解释: @Victor提供

当您去餐厅时,您会看到一个菜单,并看到几个可供选择的选项。您可以订购菜单上的任何一项或多项。但是,除非您实际订购它们,否则它们只是“用餐的机会”。一旦您下了订单,服务员就将它带到了桌上,就成了一顿饭。

连接点是菜单上的选项,“切入点”是您选择的项。

连接点是代码中供您应用方面的机会……这只是机会。抓住这个机会并选择一个或多个Joinpoint并将其应用到一个方面后,您便有了一个Pointcut。

来源Wiki

一个连接点是一个程序,控制流可以通过到达的控制流程的一个点两个不同的路径(IMO:这就是为什么叫关节)。

建议描述了一类可修改其他功能的功能

一个切入点是一组连接点。


3
这应该标记为正确答案。只是要添加更多信息,请查看Cragi Walls的答案... coderanch.com/t/485525/Spring/Difference-Joint-Point-Point-Cut
维克多2015年

2
关键点:切入点定义了应该在哪些连接点处应用建议+1
Naman Gala

只是为了确认,more Joinpoints and apply an aspect to them, you've got a Pointcut. 对他们的方面还是对他们的建议?
阿西夫·穆斯塔克

@Premraj因此,根据您的类比建议,将点餐。我对吗?
Vishwas Atrey

餐厅类比有助于消除JoinPoints和切入点之间的混淆,谢谢!
SM

30

要了解连接点和切入点之间的区别,可以将切入点视为指定编织规则,并将连接点视为满足这些规则的情况。

在下面的示例中,

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

切入点定义了规则,说,建议应应用于任何包中任何类中存在的getName()方法,而连接点将是类中存在的所有getName()方法的列表,以便可以将建议应用于这些方法。

(对于Spring,Rule仅适用于托管Bean,建议仅适用于公共方法)。


1
“切入点定义了规则,建议应将建议应用于任何包中任何类中存在的getName()方法,并且连接点将是类中存在的所有getName()方法的列表,以便可以将建议应用于这些方法。” 抱歉,这越来越令人困惑。您能在现实生活中给我一个比喻吗?
Saurabh Patil

28

JoinPoints:这些基本上是实际业务逻辑中的位置,您希望在其中插入一些必需的功能,但这些功能不是实际业务逻辑的一部分。JoinPint的一些示例包括:方法调用,方法正常返回,方法引发异常,实例化对象,引用对象等。

切入点:切入点类似于正则表达式,用于标识连接点。Pontcuts使用“切入点表达语言”表示。切入点是执行流程中需要应用横切关注点的点。Joinpoint和Pointcut之间是有区别的。连接点更通用,表示我们可以“选择”引入交叉关注点的任何控制流,而切入点标识了“我们希望”引入交叉关注点的此类连接点。


1
Joinpoint-应用/运行建议代码的潜在位置。切入点-用于执行建议的实际选择的连接点。
user104309

24

Layman对AOP概念的新手的解释。这不是穷举性的,但应该有助于理解这些概念。如果您已经熟悉基本术语,则可以立即停止阅读。

假设您有一个普通的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关键字并采取措施。一种方法是在spring config xml文件中指定以下内容:

<aop:aspectj-autoproxy>


1
我是AOP的新手,这个解释帮助我非常清楚地了解了Advice / Pointcuts / JoinPoints之间的关系。
贾汀

11

将诸如AspectJ之类的AOP语言与诸如SQL之类的数据查询语言进行比较,您可以将连接点(即代码中可以编织方面代码的所有位置)视为具有许多行的数据库表。切入点就像SELECT角色一样,可以选择用户定义的行/联接点子集。您编织到这些选定位置中的实际代码称为建议。


9

定义

根据文档:

连接点:程序执行过程中的一个点,例如方法执行或异常处理。

您可以将关节点视为程序执行中的事件。如果您使用的是Spring AOP,那么这甚至仅限于方法的调用。AspectJ提供了更大的灵活性。

但是您永远不会处理所有事件,因为去餐馆时您不会吃菜单上的所有食物(我可能不认识您,您可能会!但是,我当然不会)。因此,您可以选择要处理的事件以及如何处理它们。切入点在这里。根据文档,

切入点:与连接点匹配的谓词。

然后你联想做什么用的切入点,有云咨询。根据文档,

建议切入点表达式关联,并在与该切入点匹配的任何连接点处运行。

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

两者都属于面向方面编程的“何处”。

连接点是一个单独的位置,您可以在其中使用AOP执行代码。例如,“当方法抛出异常时”。

切入点是连接点的集合。例如,“当类Foo中的方法引发异常时”。


4

JoinPoint:Joinpoint是程序执行中的点,执行流发生了变化,例如异常捕获,调用其他方法。

PointCut:PointCut基本上是那些可以在其中放置建议(或调用方面)的联接点。

因此,基本上,PointCuts是JoinPoints的子集


3

春季的AOP中有{顾问,建议,切入点,连接点}

如您所知,aop的主要目的是将跨领域关注逻辑(Aspect)与应用程序代码分离,为了在Spring中实现这一点,我们使用(Advice / Advisor)

Pointcut用于过滤我们要确切应用此建议的位置,例如“所有方法均以insert开头”,因此将排除其他方法,这就是我们在Pointcut接口{ClassFilter和MethodMatcher}中使用的原因

因此,Advice是跨部门逻辑实现,Advisor是建议加上PointCut,如果仅使用通知,则spring会将其映射到Advisor并使切入点为TRUE,这意味着不要阻塞任何内容。这就是为什么当您仅使用建议时,它会应用到目标类的所有方法的原因,因为您没有过滤它们。

但是Joinpoint是程序中的一个位置,您可以在访问Class对象时像反射一样思考它,然后可以获取Method对象,然后可以调用此类中的任何方法,这就是编译器的工作原理,如果您认为这可以想像联接点。

Joinpoint可以与字段,构造函数或方法一起使用,但是在Spring中,我们仅具有方法的连接点,这就是为什么在Spring中,我们具有(之前,之后,抛出,周围)类型的Joinpoint,它们都引用类中的位置。

正如我提到的那样,您可以在没有切入点(没有过滤器)的情况下获得建议,那么它将被应用于所有方法,或者您可以拥有将[advice + pointcut]应用于特定方法的顾问,但是如果没有这些建议,您将无法得到建议像切入点这样的连接点,必须指定它,这就是为什么spring中的建议类型与连接点类型完全相同的原因,因此,当您选择建议时,您会隐式选择哪个连接点。

总结起来,建议是目标类的方面的实现逻辑,该建议应该具有一个连接点,如调用之前,调用之后,引发之后或周围调用,然后可以使用切入点来过滤要应用它的确切位置过滤方法或没有切入点(没有过滤器),因此它将应用于类的所有方法。


3

在Aspect-类实现上定义了一个切入点。切入点基本上是指建议中的切入点表达。

例如

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

上面的意思是,在调用任何方法之前(由于@Before的建议)(在包“ app.purchase2.service.impl”中的类中),将调用“ includeAddOns”方法

整个注释称为切入点 @Before("execution(* app.purchase2.service.impl.*(..))")

结合点是实际的方法调用,将程序包“ app.purchase2.service.impl”中的方法与方面类“ includeAddOns()”中的方法结合在一起。

您可以使用org.aspectj.lang.JoinPoint类访问连接点的属性。


好答案!最后,我明白了区别!
但丁

2

我同意mgroves的观点。切点可以看作是多个联合点的集合。联合点指定可以实施建议的特定位置,因为切入点反映了所有联合点的列表。


0

JoinPoint:它指定应用程序中将执行建议的点(方法)。

切入点:这是JoinPoints的组合,它指定执行JoinPoint通知的位置。


-5

连接点是我们实际放置建议的地方

但切入点是连接点的集合。这意味着我们如何配置横切逻辑的方法称为切点

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.