97

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

切入点的示例可以是:

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

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

4

14 回答 14

180

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

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

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

下图可以帮助你理解Advice、PointCut、Joinpoints。 在此处输入图像描述

来源

使用餐厅类比进行解释: 来源@Victor

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

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

Joinpoint 是代码中的一个机会,您可以应用一个方面……只是一个机会。一旦你抓住这个机会并选择一个或多个连接点并将一个方面应用于它们,你就有了一个切入点。

来源维基

Joinpoint是程序控制流中的一个点,控制流可以通过两条不同的路径到达(IMO:这就是为什么调用joint)。

Advice描述了修改其他函数的一类函数

切入点是连接点的匹配P模式,即连接点的集合。

于 2014-09-11T05:42:14.960 回答
33

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

在下面的例子中,

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

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

(在 Spring 的情况下,规则将仅应用于托管 bean,建议只能应用于公共方法)。

于 2013-03-18T09:29:31.327 回答
32

对 AOP 概念新手的外行解释。这并不详尽,但应该有助于掌握这些概念。如果您已经熟悉基本术语,现在可以停止阅读。

假设您有一个普通的 Employee 类,并且您希望每次调用这些方法时都做一些事情。

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

这些方法称为JoinPoints。我们需要一种方法来识别这些方法,以便框架可以在它已加载的所有 classes.methods 中找到这些方法。所以我们将编写一个正则表达式来匹配这些方法的签名。正如您将在下面看到的那样,虽然还有更多内容,但这个正则表达式松散地定义了Pointcut。例如

* * mypackage.Employee.get*(*)

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

但是,您还需要再说明两件事:

  1. 什么时候应该采取行动 - 例如在方法执行之前/之后或发生异常
  2. 匹配时应该做什么(可能只是打印一条消息)

这两者的组合称为Advice

可以想象,您必须编写一个函数才能执行 #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>

于 2016-09-02T20:15:20.227 回答
30

JoinPoints:这些基本上是实际业务逻辑中您希望插入一些杂项功能的地方,这些功能是必要的,但不是实际业务逻辑的一部分。JoinPints 的一些示例是:方法调用、方法正常返回、方法抛出异常、实例化对象、引用对象等...

切入点:切入点类似于用于识别连接点的正则表达式。使用“切入点表达语言”来表达切点。切入点是需要应用横切关注点的执行流程点。Joinpoint 和 Pointcut 是有区别的;连接点更通用,表示我们“可能选择”引入横切关注点的任何控制流,而切入点识别“我们想要”引入横切关注点的连接点。

于 2013-10-29T10:09:14.987 回答
12

将 AOP 语言(如 AspectJ)与数据查询语言(如 SQL)进行比较,

  • 您可以将连接点(即代码中可以编织方面代码的所有位置)视为具有许多行的数据库表。
  • 切入点就像一个 SELECT 语句,可以选择用户定义的行/连接点子集。
  • 您编入这些选定位置的实际代码称为建议
于 2013-03-17T18:16:38.307 回答
12

定义

根据文档:

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

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

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

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

然后你联想到Pointcut做什么,还有Advice。根据文档,

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

代码

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的是,这个使用内联切点声明

不信可以看文档。我希望这有帮助

于 2016-10-25T07:49:07.867 回答
7

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

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

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

于 2013-03-17T14:18:52.267 回答
5

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

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

所以基本上PointCuts 是 JoinPoints 的子集

于 2015-01-22T19:32:39.347 回答
3

Spring 中的 AOP 有 {Advisor, Advice, Pointcut, Joinpoint}

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

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

因此,Advice 是横切逻辑实现,Advisor 是建议加上 PointCut,如果您只使用建议,spring 会将其映射到 Advisor 并使切入点为 TRUE,这意味着不阻塞任何东西。这就是为什么当您只使用建议时,它会应用于目标类的所有方法,因为您没有过滤它们。

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

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

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

总而言之,advice 是你的方面到目标类的实现逻辑,这个advice 应该有一个连接点,比如在调用之前、调用之后、抛出之后或调用周围,然后你可以使用切入点过滤你想要应用它的确切位置过滤方法或无切入点(无过滤器),以便将其应用于类的所有方法。

于 2014-04-16T09:35:38.460 回答
3

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

例如,

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

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

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

联合点是实际的方法调用,它将包“app.purchase2.service.impl”中的方法连接到方面类“includeAddOns()”中的方法。

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

于 2015-01-24T09:21:31.900 回答
2

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

于 2013-08-18T22:50:38.893 回答
1

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

Pointcut:它是JoinPoints 的组合,它指定了JoinPoint Advice 的执行位置。

于 2013-12-29T10:53:42.977 回答
0

PointCut()是一个注解,您可以在通知应用的范围内声明范围。

相反,JoinPoint是一个接口,它是用于所有五个建议的参数。特别是对于@Around通知,应用了ProceedingJoinPoint(JoinPoint 的子接口),并提供了.proceed()方法。所以你可以控制是否让程序继续进行。您还可以更改它的参数。

于 2021-11-03T20:32:02.800 回答
-5

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

但切点是连接点的集合。这意味着我们有多少种方式来配置横切逻辑被称为切入点

于 2014-12-05T07:31:25.880 回答