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

时间:2013-03-16 08:53:47

标签: spring aop aspectj spring-aop pointcut

我正在学习面向方面的编程概念和Spring AOP。我无法理解Pointcut和Joinpoint之间的区别 - 它们对我来说似乎都是一样的。 Pointcut是您应用建议的地方,Joinpoint也是我们可以应用我们建议的地方。那有什么区别?

切入点的一个例子可以是:

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

什么是Joinpoint的例子?

13 个答案:

答案 0 :(得分:136)

加入点:加入点是应用程序的程序执行中的候选点,可以插入方面。这一点可以是一个被调用的方法,抛出的异常,甚至是被修改的字段。这些是可以将方面的代码插入到应用程序的正常流程中以添加新行为的点。

建议:这是一个对象,其中包含对系统范围关注点的API调用,表示在某个点指定的连接点执行的操作。

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

以下图片可以帮助您了解建议,PointCut,Joinpoints。 enter image description here

Source

使用餐厅类比解释: Source by @Victor

当你去餐馆时,你会看一个菜单,看看有几个选项可供选择。您可以在菜单上订购任何一个或多个项目。但是在你真正订购它们之前,它们只是“用餐的机会”。一旦你下订单,服务员把它带到你的餐桌,这是一顿饭。

Joinpoints是菜单上的选项,Pointcuts是您选择的项目。

Joinpoint是代码中的一个机会,您可以应用方面......只是一个机会。一旦你抓住这个机会并选择一个或多个Joinpoints并对它们应用一个方面,你就有了一个Pointcut。

答案 1 :(得分:27)

要理解连接点和切入点之间的区别,请考虑切入点 指定编织规则和连接点作为满足这些规则的情况。

在下面的例子中,

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

Pointcut定义规则说,建议应该应用于任何包中任何类中的getName()方法,而joinpoints将是类中存在的所有getName()方法的列表,以便可以对这些方法应用建议。 / p>

(对于Spring,Rule仅适用于托管bean,建议只能应用于公共方法。)

答案 2 :(得分:26)

JoinPoints:这些基本上位于实际业务逻辑中,您希望插入一些必要但又不属于实际业务逻辑的其他功能。 JoinPints的一些示例包括:方法调用,正常返回方法,抛出异常的方法,实例化对象,引用对象等等。

切入点:切入点类似于正则表达式,用于标识连接点。 Pontcuts使用“切入点表达式语言”表示。切入点是需要应用跨领域关注点的执行流程。 Joinpoint和Pointcut之间存在差异;连接点更为通用,代表任何控制流程,我们可以选择“引入跨领域关注点,而切入点识别此类连接点,我们希望”引入跨领域关注点。

答案 3 :(得分:19)

对于AOP概念不熟悉的人的Layman解释。这不是详尽无遗的,但应该有助于理解这些概念。如果您已熟悉基本术语,可以立即停止阅读。

假设您有一个普通的Employee类,并且每次调用这些方法时都希望执行某些操作。

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

这些方法称为 JoinPoints 。我们需要一种方法来识别这些方法,以便框架可以在所有类中找到方法。它已经加载了方法。 因此,我们将编写一个正则表达式来匹配这些方法的签名。虽然下面会有更多内容,但松散地说这个正则表达式定义了 Pointcut 。 e.g。

* * mypackage.Employee.get*(*)

First *用于修饰符public / private / protected / default。 第二个*用于方法的返回类型。

但是你还需要告诉另外两件事:

  1. 何时应采取行动 - 例如,方法执行之前/之后或异常
  2. 匹配时应该做什么(可能只是打印一条消息)
  3. 这两者的组合称为建议

    你可以想象,你必须编写一个能够做#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>

答案 4 :(得分:9)

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

答案 5 :(得分:6)

两者都与面向方面编程的“位置”有关。

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

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

答案 6 :(得分:5)

解释

根据文件:

  

加入点:执行程序时的一个点,例如   执行方法或处理异常。

您可以将关节点视为执行程序的事件。如果您使用的是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 before 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不同,这个使用内联点切割声明

如果你不相信我,可以查看documentation。我希望这有帮助

答案 7 :(得分:3)

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

PointCut :PointCut基本上就是那些你可以提出建议(或调用方面)的Joinpoints。

所以基本上 PointCuts是JoinPoints的子集

答案 8 :(得分:2)

我同意mgroves ..点切可以被视为多个关节点的集合。联合点指定可以实施建议的特定位置,其中切入点反映所有联合点的列表。

答案 9 :(得分:2)

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

例如,

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

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

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

关节点是实际的方法调用,它将包“app.purchase2.service.impl”中的方法加入了方面类“includeAddOns()”中的方法。

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

答案 10 :(得分:1)

春天的AOP有{Advisor,Advice,Pointcut,Joinpoint}

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

Pointcut用于过滤我们想要完全应用此建议的位置,例如&#34;所有方法都以insert&#34;所以其他方法将被排除,这就是我们在Pointcut界面中的原因{ClassFilter和MethodMatcher}

所以Advice是交叉逻辑实现,Advisor是建议和PointCut,如果你只使用建议spring将它映射到顾问并使切入点为TRUE,这意味着不要阻止任何东西。这就是为什么当你只使用建议时它会应用于目标类的所有方法,因为你没有过滤它们。

但是Joinpoint是程序中的一个位置,当你访问Class对象然后你可以得到Method对象时你可以把它想象成反射,那么你可以调用这个类中的任何方法,那是怎么回事编译器工作,如果你这样想,你可以想象Joinpoint。

Joinpoint可以是字段,构造函数或方法,但是在Spring中我们只有方法的joinpoint,这就是为什么在Spring中我们有(Before,After,Throws,Around)类型的Joinpoint,所有这些都指的是班上的位置。

正如我所提到的,您可以获得没有切入点的建议(没有过滤器),然后它将应用于所有方法,或者您可以拥有[advice + pointcut]的顾问,它将应用于特定方法,但您可以&#39 ; t没有像pointcut这样的连接点的建议,你必须指定它,这就是为什么spring中的建议类型与连接点完全相同的类型,所以当你选择建议时,你隐式选择哪个连接点。

总结一下,advice是你的方面到目标类的实现逻辑,这个建议应该有一个像调用之前,调用之后,抛出之后或调用之后的连接点,然后你可以过滤你想要应用它的确切位置使用切入点过滤方法或没有切入点(没有过滤器),因此它将应用于类的所有方法。

答案 11 :(得分:-2)

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

切入点:这是JoinPoints的组合,它指定将执行JoinPoint建议。

答案 12 :(得分:-5)

加入点是我们实际放置建议的地方

但是切入点是连接点的集合。这意味着我们将横切逻辑的多少方式称为切点