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

我正在学习面向方面的编程概念和Spring AOP。 我不明白一个切入点和一个连接点的区别 – 他们两个对我来说似乎都是一样的。 切入点是你应用你的build议的地方,一个连接点也是我们可以应用我们的build议的地方,那么有什么区别?

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

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

什么可以是一个Joinpoint的例子?

连接点连接点是应用程序的程序执行的一个候选点,一个方面可以被插入。这一点可能是被调用的方法,抛出的exception,甚至是被修改的字段。 这些是您的方面的代码可以插入到您的应用程序的正常stream程添加新的行为。

build议:这是一个包含API调用的系统广泛关注的对象,表示要在由点指定的连接点执行的操作。

切入点:切入点定义在什么连接点上,应该应用相关的build议。 build议可以应用于AOP框架支持的任何连接点。 当然,你不想在所有可能的连接点上应用你所有的方面。 切入点允许您指定要将您的build议应用于何处。 通常使用显式的类和方法名称或通过定义匹配的类和方法名称模式的正则expression式来指定这些切入点。 某些AOP框架允许您创builddynamic切入点,以决定是否应用基于运行时决策的build议,如方法参数的值。

以下图片可以帮助您了解build议,PointCut,连接点。 在这里输入图像说明

资源

使用餐厅类比的解释: 来自@Victor

当你去一家餐馆,你看看一个菜单,看到几个选项可供select。 您可以订购一个或多个菜单上的任何项目。 但是,直到你真正点餐,他们才是“吃饭的机会”。 一旦你下了订单,服务员把它带到你的桌子,这是一顿饭。

join点是菜单上的选项,切入点是您select的项目。 连接点是代码中的一个机会,您可以应用一个方面…只是一个机会。 一旦你抓住这个机会,select一个或多个连接点并对其应用一个方面,你就有了一个切入点。

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

在下面的例子中,

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

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

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

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

切入点:切入点就像用于识别连接点的正则expression式。 切入点使用“切入点expression式语言”来表示。 切入点是需要应用交叉关注点的执行stream程点。 Joinpoint和Pointcut是有区别的; 连接点更一般,代表任何控制stream程,我们可以select“引入横切关注点,而切入点标识这样的连接点,”我们想要“引入横切关注点。

对于AOP这个概念的新手来说,一个人的解释。 这不是详尽的,但应该有助于理解概念。 如果您已经熟悉了这个基本的术语,现在可以停止阅读了。

假设你有一个普通的Employee类,每次调用这些方法时你都想做一些事情。

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

这些方法被称为JoinPoints 。 我们需要一种方法来识别这些方法,以便框架能够find它所加载的所有类中的方法。 所以我们将编写一个正则expression式来匹配这些方法的签名。 正如你将会在下面看到的那样,但是这个正则expression式可以松散地定义Pointcut 。 例如

 * * mypackage.Employee.get*(*) 

第一个*是修饰符public / private / protected / default。 第二个*是方法的返回types。

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

  1. 什么时候应该采取行动 – 例如在方法执行之前/之后或exception
  2. 匹配时应该做什么(也许只是打印一条消息)

这两个组合被称为build议

你可以想象,你将不得不写一个函数来做#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通知。 反复的正则expression式最终会使事情变得混乱和难以维护。 所以我们做什么,我们只是给expression式一个名字,并在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 public class MyAwesomeAspect{....} 

为了使所有这些工作起作用,你必须告诉Spring分析这些类来​​阅读,理解和对@ AOP关键字采取行动。 一种方法是在spring config xml文件中指定以下内容:

<aop:aspectj-autoproxy>

将像AspectJ这样的AOP语言与数据查询语言(如SQL)进行比较,可以将连接点(即代码中可编排方面代码的所有位置)想象为具有多行的数据库表。 切入点就像一个SELECT stamement,它可以select用户定义的行/连接点子集。 你编织到这些选定的地方的实际代码被称为build议。

两者都涉及面向方面编程的“哪里”。

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

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

我同意mgroves ..减分可以被认为是多个联合点的集合。 联合点指定build议可以实施的特定位置,切入点反映所有联合点的列表。

JoinPoint :Joinpoint是程序执行过程中的一些点,执行stream程如exception捕获,调用其他方法。

PointCut :PointCut基本上就是你可以把你的build议(或称为方面)的那些连接点。

所以基本上PointCuts是JoinPoints的子集

定义

根据文件:

join点:程序执行期间的一个点,例如执行方法或处理exception。

您可以将联合点视为执行程序中的事件。 如果你正在使用Spring AOP,这甚至限于调用方法。 AspectJ提供了更多的灵活性。

但是你从不处理所有的事情,因为当你去一家餐馆的时候,你没有在菜单中吃所有的食物(我不认识你,你可能会的,但我当然不会)。 因此,您可以select要处理的事件以及如何处理这些事件。 这里是切入点 。 根据文件,

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

然后你把这个切入点联系起来 ,那里有build议 。 根据文件,

build议切入点expression式相关联,并在切入点匹配的任何连接点处运行。

 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()是一个build议 ,将执行后,我们的somePointCut 点削减 ,匹配doYourBusiness() 联合点
  • beforeSomePointCut()也是一个与所有public方法执行相匹配的通知 。 与afterSomePointCut不同的afterSomePointCut ,这个使用了内联的切点声明

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

切入点是在Aspect类实现上定义的。 切入点基本上是指build议内的切入点expression式。

例如,

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

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

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

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

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

AOP在spring{顾问,build议,切入点,连接点}

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

切入点用于过滤我们想要准确应用这个build议的位置,比如“所有的方法都以插入开始”,所以其他方法将被排除,这就是为什么我们在切入点接口{ClassFilter和MethodMatcher}

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

但是Joinpoint是程序中的一个位置,你可以在访问Class对象的时候考虑它,然后你可以获得Method对象,那么你可以调用这个类的任何方法,这就是编译器的工作方式,如果你想你可以想象这个连接点。

Joinpoint可以与字段,构造函数或方法一起使用,但是在Spring中我们只有方法的连接点,这就是为什么在Spring中我们有(Before,After,Throws,Around)types的Joinpoint,它们都指向类中的位置。

正如我所说,你可以有没有切入点的build议(没有filter),那么它将被应用到所有的方法,或者你可以有顾问是[advice + pointcut]将被应用于特定的方法,但你不能没有build议没有像切入点一样的连接点,你必须指定它,这就是为什么spring的build议types和连接点types完全一样,所以当你select一个build议时,你隐式地select了哪个连接点。

总结一下,build议是你的方面到目标类的实现逻辑,这个build议应该像在调用之前,在调用之后,在抛出之后或者在调用之前有一个连接点,然后你可以使用pointcut来过滤你想要应用的地方过滤方法或没有切入点(没有filter),所以它将被应用到类的所有方法。

JoinPoint:它指定了一个应用程序中的一个点(方法),其中将执行build议。

切入点:它是JoinPoints的组合,它指定了在哪个JoinPointbuild议将被执行。

join点是我们实际提出意见的地方

但是切点是连接点的集合。 这意味着我们将交叉逻辑的多less方式称为点削减

Interesting Posts