Spring AOP中Pointcut,dvice 和 Advisor三个概念

本文介绍了Spring AOP中的三个核心概念:Pointcut、Advice和Advisor,并详细阐述了它们的作用及相互之间的关系。同时,还介绍了Spring提供的三种Pointcut实现方式,包括静态切入点、动态切入点和自定义切入点。

Spring  AOP中Pointcut,dvice 和 Advisor三个概念介绍

在理解了Spring的AOP后,需要重点理解的三个概念是:Pointcut    Advice   Advisor

(1)切入点  Pointcut

              在介绍Pointcut之前,有必要先介绍  Join  Point(连接点)概念。

                         连接点:程序运行中的某个阶段点,比如方法的调用、异常的抛出等。比如方法doSome();

Pointcut是JoinPoint的集合,它是程序中需要注入Advice 的位置的集合,指明Advice要在什么样的条件下才能被触发。

               org.springframework.aop.Pointcut接口用来指定到特定方法,

//源代码

                  public InterfacePointcut{

                     //用来将切入点限定在给定的目标类中

 ClassFilter   getClassFilter();

                     //用来判断切入点是否匹配目标类的给定的方法

  MethodMatcher  getMethodMatcher();

                       Pointcut   TRUE=TruePointcut.INSTANCE;

                  }

                  在Pointcut接口中主要有两个接口:ClassMatcher和MethodMatcer,有利于代码的重用。

(2)通知Advice

 它是某个连接点所采用的处理逻辑,也就是向连接点注入的代码。例如:输出的日志信息   就是一个Advice

(3)Advisor

Advisor是Pointcut和Advice的配置器,它包括PointcutAdvice,是将Advice注入程序中Pointcut位置的代码

----------------------------------------------------------------------------------------------------------------------------

AOP的3个关键概念

  因为AOP的概念难于理解,所以在前面首先对Java动态代理机制进行了一下讲解,从而使读者能够循序渐进地来理解AOP的思想。

学习AOP,关键在于理解AOP的思想,能够使用AOP。对于AOP众多的概念,读者只要理解3个重要的概念即可。这3个概念是Pointcut、Advice和Advisor。

1  切入点(Pointcut)

  在介绍Pointcut前,有必要先介绍一下Join Point(连接点)的概念。Join Point指的是程序运行中的某个阶段点,如某个方法调用、异常抛出等。前面示例中的doAuditing()方法就是一个Join Point,表示程序是要在这个地方加入Advice。

Pointcut是Join Point的集合,它是程序中需要注入Advice的位置的集合,指明Advice要在什么样的条件下才能被触发。

org.springframework.aop.Pointcut 接口用来指定通知到特定的类和方法。查看Spring下载包里的源文件Pointcut.java,路径是spring-framework-2.0-

m1/src/org/springframework/aop,可以看到Pointcut.java.源代码如下:

1
2
3
4
5
6
7
8
9
//******* Pointcut.java**************
package  org.springframework.aop;
public  interface  Pointcut {
          //用来将切入点限定在给定的目标类中
          ClassFilter getClassFilter();
          //用来判断切入点是否匹配目标类给定的方法
          MethodMatcher getMethodMatcher();
          Pointcut TRUE = TruePointcut.INSTANCE;
}


代码说明:

  接口ClassFilter,用来将切入点限定在给定的目标类中。

  接口MethodMatcher,用来判断切入点是否匹配目标类给定的方法。

从上面可以看出,在接口Pointcut中,主要包含两个接口:ClassFilter和MethodMatcher,有利于代码的重用。


2  通知(Advice)

Advice是某个连接点所采用的处理逻辑,也就是向连接点注入的代码。前面示例中提取出来输出日志信息的代码就是一个Advice,表示要在Join Point加入这

段代码。

3  Advisor

Advisor是Pointcut和Advice的配置器,它包括Pointcut和Advice,是将Advice注入程序中Pointcut位置的代码。

上面只是粗略地对AOP的3个概念进行一下说明,目的是让读者能够较快地进入到AOP中,接下来将会分别对这3个概念进行更加详细的讲解。


Spring的3种切入点(Pointcut)实现

Pointcut是Join Point的集合,它是程序中需要注入Advice的位置的集合。Spring主要提供了3种切入点(Pointcut)的实现:静态切入点、动态切入点和自定义切入点,下面分别进行讲解。

1  静态切入点

  静态切入点只限于给定的方法和目标类,而不考虑方法的参数。Spring在调用静态切入点时只在第一次的时候计算静态切入点的位置,然后把它缓存起来,

后就不需要再进行计算。使用org.springframework.aop.support.RegexpMethodPointcut 可以实现静态切入点,RegexpMethodPointcut是一个通用的正则表达

式切入点,它是通过Jakarta ORO来实现的,需要把jakarta-oro-2.0.8.jar加入到ClassPath中,它的正则表达式语法和Jakarta ORO的正则表达式语法是一样

的。使用RegexpMethodPointcut的一个示例代码如下:

<bean id="settersAndAbsquatulatePointcut"

   class="org.springframework.aop.support.RegexpMethodPointcut">

   <property name="patterns">

       <!--设定切入点-->

<list>

           <value>.*save.*</value>

           <value>.*do.* </value>

       </list>

   </property>

</bean>

代码说明:

.*save.*,表示所有以save开头的方法都是切入点。

 .* do.*,表示所有以do开头的方法都是切入点。

2  动态切入点

   动态切入点与静态切入点的区别是,它不仅限定于给点的方法和类,动态切入点还可以指定方法的参数。因为参数的变化性,所以动态切入点不能缓存,需要每次调用的时候都进行计算,因此使用动态切入点有很大的性能损耗。当切入点需要在执行时根据参数值来调用通知时,就需要使用动态切入点。Spring提供了一个内建的动态切入点:控制流切入点。此切入点匹配基于当前线程的调用堆栈。开发人员只有在当前线程执行时找到特定的类和特定的方法才返回true。其实大多数的切入点可以使用静态切入点,所以很少有机会创建动态切入点。

3  自定义切入点

   因为Spring中的切入点是Java类,而不是语言特性(如AspectJ),因此可以定义自定义切入点。因为AOP还没有完全成熟,Spring提供的文档在这方面也没有提供更详细的解释,所以这里将不再对动态切入点和自定义切入点进行更加详细的介绍。

<think> 首先,用户的问题是:“我想了解Spring AOP中@Pointcut的相关信息,可能包括使用方法、原理、示例等 请问Spring AOP中@Pointcut的使用方法原理”。用户要求我参考提供的引用内容,这些引用是关于Spring AOP中@Pointcut的。 引用内容: - 引用[1]:讨论了@Pointcut注解在Spring Boot AOP中的作用,允许定义切点并应用通知。 - 引用[2]:描述了使用"bean(...)"匹配Spring bean的方法调用。 - 引用[3]:提到定义Pointcut后,在通知中使用它。 - 引用[4]:介绍了AspectJ框架与Spring AOP的集成,以及定义切入点的步骤。 - 引用[5]:提供了@Pointcut注解的细节,包括valueargNames选项。 我的回答需要: - 使用中文回答。 - 结构清晰,帮助用户逐步解决问题。 - 确保回答真实可靠。 - 对于行内数学表达式,使用$...$格式;对于独立公式,使用$$...$$格式并单独成段。但在这个主题中,可能没有数学表达式,所以我可以忽略这一点。 - 生成相关问题。 - 在回答中引用的段落末尾自然地添加引用标识,如[^1]。 回答结构: 1. **引言**:简要介绍@Pointcut的作用重要性。 2. **使用方法**:解释如何定义使用@Pointcut,包括语法示例。 3. **原理**:解释@Pointcut的工作原理,基于AOP概念。 4. **示例**:提供代码示例来演示@Pointcut。 5. **总结**:重申关键点。 6. **相关问题**:生成相关问题。 使用引用: - 我需要自然地融入引用内容。例如: - 引用[1]提到@Pointcut用于定义切点应用通知。 - 引用[2]说明如何使用"bean(...)"匹配。 - 引用[3]展示在通知中使用Pointcut。 - 引用[4]讨论AspectJ与Spring AOP的集成。 - 引用[5]给出@Pointcut注解的选项。 确保回答可靠: - 基于我对Spring AOP的知识,结合引用内容。 - Spring AOP基于代理机制,使用AspectJ的切点表达式。 最终输出: - 回答主体。 - 相关问题列表。 相关问题生成: - 基于主题,生成3-5个相关问题,如优化、常见错误、高级用法等。 - 格式如示例所示:§§相关问题§§ 然后列出问题。 </think>### Spring AOP中@Pointcut的使用方法原理 在Spring AOP(面向切面编程)中,`@Pointcut`注解用于定义切点(Pointcut),即指定在哪些方法或位置应用通知(Advice)。切点是AOP的核心,它允许开发者声明式地定义横切关注点(如日志、事务管理),从而实现代码的解耦重用[^1]。下面我将逐步解释其使用方法、原理,并提供示例。 #### 1. **@Pointcut的使用方法** `@Pointcut`的使用主要包括定义切点表达式在通知中引用它。切点表达式使用AspectJ语法,Spring AOP基于此语法实现匹配。 - **基本语法**: - 使用`@Pointcut`注解定义一个方法(通常为空方法),其`value`属性指定切点表达式。 - 表达式可以匹配方法调用、类、参数等。例如: - `execution(* com.example.service.*.*(..))`:匹配`com.example.service`包下所有类的所有方法。 - `bean(userService)`:匹配Spring容器中ID为`userService`的bean的所有方法调用(基于引用[2]的解释)[^2]。 - 切点方法在Aspect类中定义,并使用`@Aspect`标注该类。 - **定义引用步骤**: 1. **创建Aspect类**:使用`@Aspect`标注一个类,并在其中定义`@Pointcut`。 2. **定义切点**:编写一个空方法,添加`@Pointcut`注解。 3. **应用通知**:在通知(如`@Before`、`@After`)中引用该切点(引用[3]中的示例)[^3]。 - **代码示例**: 假设我们有一个服务类`UserService`,需要记录其所有方法的执行日志。 ```java import org.aspectj.lang.annotation.*; import org.springframework.stereotype.Component; @Aspect @Component public class LoggingAspect { // 定义切点:匹配UserService的所有方法 @Pointcut("bean(userService)") // 基于引用[2],使用bean表达式匹配特定bean public void userServicePointcut() {} // 在通知中引用切点 @Before("userServicePointcut()") // 方法执行前应用通知 public void logBefore() { System.out.println("方法开始执行..."); } } ``` 在这个示例中: - `@Pointcut("bean(userService)")`定义了切点,匹配`userService` bean的所有方法。 - `@Before`通知引用了该切点,在方法执行前打印日志。 - **高级用法**: - **参数匹配**:使用`argNames`属性指定参数名(引用[5]),例如`@Pointcut(value = "execution(* save(..)) && args(user)", argNames = "user")`匹配`save`方法并捕获`user`参数[^5]。 - **组合表达式**:使用`&&`、`||`组合多个切点,提升灵活性。 - **集成AspectJ**:Spring AOP可以与AspectJ框架集成(引用[4]),支持更强大的切点定义,如基于注解的匹配(如`@annotation(org.springframework.transaction.annotation.Transactional)`)[^4]。 #### 2. **@Pointcut的原理** `@Pointcut`的工作原理基于Spring AOP的代理机制AspectJ的切点模型,核心是运行时动态生成代理对象。 - **代理机制**: - Spring AOP通过JDK动态代理或CGLIB代理创建目标对象的代理。当方法被调用时,代理拦截调用,并根据切点表达式决定是否应用通知。例如,如果切点匹配方法,则执行相关通知(如`@Before`)[^1]。 - 这个过程在Spring容器初始化时完成:Spring扫描`@Aspect`类,解析`@Pointcut`定义,并生成代理bean(引用[4]中的步骤)[^4]。 - **切点表达式解析**: - 切点表达式在编译或运行时被解析为匹配规则。例如,`execution(* *.*(..))`会被转换为字节码级别的匹配逻辑。 - 匹配基于方法签名:包括类名、方法名、参数类型返回类型。Spring使用AspectJ weaver(编织器)在运行时应用这些规则(AspectJ提供底层支持)[^4][^5]。 - **性能考虑**: - 切点表达式的复杂度影响性能。简单表达式(如`bean(...)`)高效,而复杂表达式(涉及通配符或参数匹配)可能增加运行时开销。优化时,应优先使用具体匹配减少扫描范围[^2][^5]。 - **与AspectJ的关系**: - Spring AOP是AspectJ的子集,专注于方法级别的切面(引用[4])。AspectJ提供更全面的AOP功能(如构造函数切点),但Spring AOP通过集成简化了使用。原理上,`@Pointcut`注解最终由AspectJ引擎处理[^4][^5]。 #### 3. **实际应用建议** - **最佳实践**: - 将切点定义在单独方法中,便于重用(如示例中的`userServicePointcut()`)。 - 测试切点时,使用单元测试验证匹配准确性。 - 避免过度使用复杂表达式,以保持性能。 - **常见问题**: - 如果切点不生效,检查表达式是否正确或Spring配置是否启用AOP(如添加`@EnableAspectJAutoProxy`)。 - 参数匹配错误时,确保`argNames`与通知方法参数一致(引用[5])[^5]。 总结来说,`@Pointcut`是Spring AOP实现横切关注点的关键工具,它通过声明式表达式定义应用通知的位置,提升代码模块化[^1]。结合AspectJ的强大功能,开发者可以高效地处理日志、安全等通用逻辑[^4]。
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值