SpringAOP中Aspect优先级与切面表达式详解

简介: SpringAOP中Aspect优先级与切面表达式详解

【1】Aspect优先级

在同一个连接点上应用不止一个切面时, 除非明确指定, 否则它们的优先级是不确定的。

切面的优先级可以通过实现 Ordered 接口或利用 @Order 注解指定.

实现 Ordered 接口, getOrder() 方法的返回值越小, 优先级越高;
若使用 @Order 注解, 序号出现在注解中。

【2】@Pointcut重用切入点定义


在编写 AspectJ 切面时, 可以直接在通知注解中书写切入点表达式。但同一个切点表达式可能会在多个通知中重复出现。


在 AspectJ 切面中, 可以通过 @Pointcut 注解将一个切入点声明成简单的方法。切入点的方法体通常是空的, 因为将切入点定义与应用程序逻辑混在一起是不合理的。


切入点方法的访问控制符同时也控制着这个切入点的可见性。


如果切入点要在多个切面中共用, 最好将它们集中在一个公共的类中。在这种情况下, 它们必须被声明为 public。 在引入这个切入点时, 必须将类名也包括在内。 如果类没有与这个切面放在同一个包中, 还必须包含包名。


其他通知可以通过方法名称引入该切入点。匹配ArithmeticCalculatorImpl下参数为(int,int)的所有方法:

@Pointcut("execution(int com.web.aop.impl.ArithmeticCalculatorImpl.*(int , int ))")
public void declareJoinPointExpression() {
}


匹配controller包下的所有类的所有方法:

 @Pointcut("execution(* com.recommend.controller.*.*(..))")
 public void declareJoinPointExpression() {
}


【3】AspectJ 切入点表达式

最典型的切入点表达式时根据方法的签名来匹配各种方法

  • execution * com.web.spring.ArithmeticCalculator.*(..)
匹配 ArithmeticCalculator 中声明的所有方法;
第一个 * 代表任意修饰符及任意返回值. 
第二个 * 代表任意方法;
'..' 匹配任意数量的参数. 
若目标类与接口与该切面在同一个包中, 可以省略包名.

execution public * ArithmeticCalculator.*(..)


匹配 ArithmeticCalculator 接口的所有公有方法.


execution public double ArithmeticCalculator.*(..)


匹配 ArithmeticCalculator 中返回 double 类型数值的方法


execution public double ArithmeticCalculator.*(double, ..)

匹配第一个参数为 double 类型,结果返回类型为double类型的方法, ‘..’ 匹配任意数量任意类型的参数


execution public double ArithmeticCalculator.*(double, double)

匹配参数类型为 double, 返回double 类型的方法.

【4】其他的切入点类型完整的AspectJ切入点语言支持额外的切入点指定者,但是Spring不支持这个功能。 他们分别是call, initialization, preinitialization, staticinitialization, get, set, handler, adviceexecution, withincode, cflow, cflowbelow, if, @this 和 @withincode。


在Spring AOP中使用这些指定者将会导致抛出IllegalArgumentException异常。


Spring AOP支持的切入点指定者可能在将来的版本中得到扩展,不但支持更多的AspectJ 切入点指定者(例如"if"),还会支持某些Spring特有的切入点指定者,比如"bean"(用于匹配bean的名字)。


execution - 匹配方法执行的连接点,这是你将会用到的Spring的最主要的切入点指定者。


within - 限定匹配特定类型的连接点(在使用Spring AOP的时候,在匹配的类型中定义的方法的执行)。


this - 限定匹配特定的连接点(使用Spring AOP的时候方法的执行),其中bean reference(Spring AOP 代理)是指定类型的实例。


target - 限定匹配特定的连接点(使用Spring AOP的时候方法的执行),其中目标对象(被代理的appolication object)是指定类型的实例。


args - 限定匹配特定的连接点(使用Spring AOP的时候方法的执行),其中参数是指定类型的实例。


@target - 限定匹配特定的连接点(使用Spring AOP的时候方法的执行),其中执行的对象的类已经有指定类型的注解。


@args - 限定匹配特定的连接点(使用Spring AOP的时候方法的执行),其中实际传入参数的运行时类型有指定类型的注解。


@within - 限定匹配特定的连接点,其中连接点所在类型已指定注解(在使用Spring AOP的时候,所执行的方法所在类型已指定注解)。


@annotation - 限定匹配特定的连接点(使用Spring AOP的时候方法的执行),其中连接点的主题有某种给定的注解。


因为Spring AOP限制了连接点必须是方法执行级别的,pointcut designators的讨论也给出了一个定义,这个定义和AspectJ的编程指南中的定义相比显得更加狭窄。


除此之外,AspectJ它本身有基于类型的语义,在执行的连接点’this’和’target’都是指同一个对象,也就是执行方法的对象。


Spring AOP是一个基于代理的系统,并且严格区分代理对象本身(对应于’this’)和背后的目标对象(对应于’target’)

【5】合并切入点表达式

切入点表达式可以使用'&&', '||' 和 '!'来合并。还可以通过名字来指向切入点表达式。

以下的例子展示了三种切入点表达式:

anyPublicOperation(在一个方法执行连接点代表了任意public方法的执行时匹配);
inTrading(在一个代表了在交易模块中的任意的方法执行时匹配) ;
tradingOperation(在一个代表了在交易模块中的任意的公共方法执行时匹配)。

实例如下:

  @Pointcut("execution(public * *(..))")
    private void anyPublicOperation() {}
    @Pointcut("within(com.someapp.trading..*")
    private void inTrading() {}
    @Pointcut("anyPublicOperation() && inTrading()")
    private void tradingOperation() {}



就上所示的,从更小的命名组件来构建更加复杂的切入点表达式是一种最佳实践。 当用名字来指定切入点时使用的是常见的Java成员可视性访问规则。


比如说,你可以在同一类型中访问私有的切入点,在继承关系中访问受保护的切入点,可以在任意地方访问公共切入点。 成员可视性访问规则不影响到切入点的 匹配。


目录
相关文章
|
SQL 关系型数据库 MySQL
解决MySQL主从慢同步问题的常见的解决方案:
解决MySQL主从慢同步问题的方法有很多,以下是一些常见的解决方案: 1. 检查网络连接:确保主从服务器之间的网络连接稳定,避免网络延迟或丢包导致数据同步缓慢。 2. 优化数据库配置:调整MySQL的配置参数,如增大binlog文件大小、调整innodb_flush_log_at_trx_commit等参数,以提高主从同步性能。 3. 检查IO线程和SQL线程状态:通过SHOW SLAVE STATUS命令检查IO线程和SQL线程的状态,确保它们正常运行并没有出现错误。 4. 检查主从日志位置:确认主从服务器的binlog文件和位置是否正确,避免由于错误的日志位置导致同步延迟。 5.
1696 1
|
Web App开发 编解码 安全
【WebRTC 入门教程】全面解析WebRTC:从底层原理到Qt和FFmpeg的集成应用
【WebRTC 入门教程】全面解析WebRTC:从底层原理到Qt和FFmpeg的集成应用
5665 2
|
缓存 Java Spring
【小家Spring】Spring AOP核心类Pointcut解析,对PointcutExpression切点表达式解析原理分析(以AspectJExpressionPointcut为例)(上)
【小家Spring】Spring AOP核心类Pointcut解析,对PointcutExpression切点表达式解析原理分析(以AspectJExpressionPointcut为例)(上)
【小家Spring】Spring AOP核心类Pointcut解析,对PointcutExpression切点表达式解析原理分析(以AspectJExpressionPointcut为例)(上)
|
11月前
|
消息中间件 存储 Java
Kafka 如何避免重复消费?
在Apache Kafka中,避免消息的重复消费是确保数据准确处理的关键。本文详细介绍了七种避免重复消费的方法:使用消费者组、幂等生产者、事务性生产者与消费者、手动提交偏移量、外部存储管理偏移量、去重逻辑及幂等消息处理逻辑。每种方法均有其优缺点,可根据实际需求选择合适方案。结合消费者组、手动提交偏移量和幂等处理逻辑通常是有效策略,而对于高一致性要求,则可考虑使用事务性消息。
1720 0
|
存储 Java 应用服务中间件
Java规则引擎Drools急速入门
Java规则引擎Drools急速入门
Java规则引擎Drools急速入门
|
Java 微服务 Spring
【Spring Cloud】spring cloud 调用feign请求超时 feign.RetryableException: Read timed out executing POST
【Spring Cloud】spring cloud 调用feign请求超时 feign.RetryableException: Read timed out executing POST
2280 0
|
Java 编译器 Spring
面试突击78:@Autowired 和 @Resource 有什么区别?
面试突击78:@Autowired 和 @Resource 有什么区别?
15002 5
|
存储 NoSQL Redis
RedisTemplate常用方法总结
RedisTemplate常用方法总结
683 1
|
数据可视化 Java Apache
Maven Dependency Tree:深入理解你的项目依赖
Maven Dependency Tree:深入理解你的项目依赖
2325 0

热门文章

最新文章