Spring AOP 切点表达式execution和args的区别

本文详细介绍了Spring AOP中execution()和args()切点表达式的区别。execution()关注方法定义的参数类型,args()则关注实际运行时传入的参数类型。通过示例代码,展示了这两个表达式在实际场景中的应用和匹配逻辑。理解这两者之间的差异对于正确地使用Spring AOP进行方法拦截至关重要。
摘要由CSDN通过智能技术生成

AspectJ 在实现 AOP 过程中提供了丰富的切点表达式用于表述满足条件的目标方法,如executionwithinthistargetargs 等表达式,它们各自通过自身的特征来匹配符合条件的目标方法。

我们这里讲一下 execution()args()表达式的区别。
在这里插入图片描述

execution()args()表达式的区别

在这里插入图片描述
args 表达式可以限制连接点匹配参数为指定类型的执行方法,而 execution 表达式同样可以实现限制连接点匹配参数的指定类型,那么这两个表达式具体匹配的效果有什么区别呢?

如下有两个表达式:

args(java.io.Serializable)
#--------------------
execution(* *(java.io.Serializable))

第一个args表达式表示对于任意方法,匹配方法只有一个入参且该入参实现了Serializable接口,第二个表达式表示的含义类似。

args(java.io.Serializable) 表达式匹配在执行方法时 传入目标方法的参数对象是否实现了Serializable接口。对于任意方法,执行方法时传入参数只有一个且该参数的类型实现Serializable接口则满足表达式。

execution(* *(java.io.Serializable))表达式则匹配方法定义的形参是否为Serializable。对于任意方法,方法定义时指定的形参只有一个且该参数类型为 Serializable则满足表达式。

args情形

在这里插入图片描述

execution情形

在这里插入图片描述

换言之,args表达式专注于那些在运行期间执行方法时实际传入的参数类是否实现了Serializable,而execution则专注于方法的定义里面形参类型是否为Serializable

示例

下面编写一段代码来验证上面的逻辑:

@Data
public class UserDTO implements Serializable{
	private String name;
}

@Service
public class DemoService{
	// 符合 args(java.io.Serializable) 表达式,但不限定与该方法
	public void method_1(Object obj){
		log.info("method_1's param is {}",obj)
	}

	// 符合 execution(* *(java.io.Serializable)) 表达式
	public void method_2(Serializable user){
		log.info("method_2's param is {}",user);
	}
	
	// 不符合 execution(* *(java.io.Serializable)) 表达式
	// 因为 execution 要求参数类型完全匹配,而不是继承或者实现关系
	public void method_3(UserDTO user){
		log.info("method_3's param is {}",user);
	}
}

@Aspect
@Component
public class DemoAspect{
	
    @Pointcut("execution(* com.example..*.*(..))")
    public void cut1(){}

    @Before("execution(* com.example..*.*(java.io.Serializable))")
    public void execution(JoinPoint joinPoint) throws Throwable {
        log.info("{} has executed by execution ---",joinPoint.getSignature().getName());
    }

    @Before("cut1() && args(java.io.Serializable)")
    public void args(JoinPoint joinPoint) throws Throwable {
        log.info("{} has executed by args ===",joinPoint.getSignature().getName());
    }
}

@RestController
public class DemoController{

    @Autowired
    DemoService demoService;

    @GetMapping("test1")
    public void test1(){
        final UserDTO user = new UserDTO();
        user.setName("ghimi");
        demoService.method_1(user);
    }

    @GetMapping("test2")
    public void test2(){
        final UserDTO user = new UserDTO();
        user.setName("ghimi");
        demoService.method_2(user);
    }
}

对于上述示例,当我请求 test1() 时,切面 method_1被匹配并调用,当我请求 test2()时,切面method_2被匹配并调用。由此可见args匹配的是运行时期传入的参数,而 execution匹配的是方法定义的参数。

两者同时使用时,如果传入参数同时满足executionargs表达式时,则会优先匹配 args 条件,然后匹配execution条件。

如上面的示例,当我请求 demoService.method_2()时,方法既满足 execution(* *(java.io.Serializable))表达式,又同时满足 args(java.io.Serializable) 表达式,此时会先匹配 args 表达式,然后匹配 execution表达式。

参考资料

Spring AOP 切点指示符中execution和args的区别
AOP with Spring
Introduction of Spring AOP
Join Point Matching based on Annotations
spring学习笔记-切点表达式函数详解

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值