Spring Aop(三)——Pointcut表达式介绍

简介: 3 Pointcut表达式介绍 3.1 表达式类型 标准的Aspectj Aop的pointcut的表达式类型是很丰富的,但是Spring Aop只支持其中的9种,外加Spring Aop自己扩充的一种一共是10种类型的表达式,分别如下。

3 Pointcut表达式介绍

3.1 表达式类型

标准的Aspectj Aop的pointcut的表达式类型是很丰富的,但是Spring Aop只支持其中的9种,外加Spring Aop自己扩充的一种一共是10种类型的表达式,分别如下。

  • execution:一般用于指定方法的执行,用的最多。
  • within:指定某些类型的全部方法执行,也可用来指定一个包。
  • this:Spring Aop是基于代理的,生成的bean也是一个代理对象,this就是这个代理对象,当这个对象可以转换为指定的类型时,对应的切入点就是它了,Spring Aop将生效。
  • target:当被代理的对象可以转换为指定的类型时,对应的切入点就是它了,Spring Aop将生效。
  • args:当执行的方法的参数是指定类型时生效。
  • @target:当代理的目标对象上拥有指定的注解时生效。
  • @args:当执行的方法参数类型上拥有指定的注解时生效。
  • @within:与@target类似,看官方文档和网上的说法都是@within只需要目标对象的类或者父类上有指定的注解,则@within会生效,而@target则是必须是目标对象的类上有指定的注解。而根据笔者的测试这两者都是只要目标类或父类上有指定的注解即可。
  • @annotation:当执行的方法上拥有指定的注解时生效。
  • bean:当调用的方法是指定的bean的方法时生效。

3.2 使用示例

3.2.1 execution

execution是使用的最多的一种Pointcut表达式,表示某个方法的执行,其标准语法如下。

execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? 
	name-pattern(param-pattern) throws-pattern?)

modifiers-pattern表示方法的访问类型,public等;ret-type-pattern表示方法的返回值类型,如String表示返回类型是String,“*”表示所有的返回类型;declaring-type-pattern表示方法的声明类,如“com.elim..*”表示com.elim包及其子包下面的所有类型;name-pattern表示方法的名称,如“add*”表示所有以add开头的方法名;param-pattern表示方法参数的类型,name-pattern(param-pattern)其实是一起的表示的方法集对应的参数类型,如“add()”表示不带参数的add方法,“add(*)”表示带一个任意类型的参数的add方法,“add(*,String)”则表示带两个参数,且第二个参数是String类型的add方法;throws-pattern表示异常类型;其中以问号结束的部分都是可以省略的。

  • 1、“execution(* add())”匹配所有的不带参数的add()方法。
  • 2、“execution(public * com.elim..*.add*(..))”匹配所有com.elim包及其子包下所有类的以add开头的所有public方法。
  • 3、“execution(* *(..) throws Exception)”匹配所有抛出Exception的方法。

3.2.2 within

within是用来指定类型的,指定类型中的所有方法将被拦截。

  • 1、“within(com.elim.spring.aop.service.UserServiceImpl)”匹配UserServiceImpl类对应对象的所有方法外部调用,而且这个对象只能是UserServiceImpl类型,不能是其子类型。
  • 2、“within(com.elim..*)”匹配com.elim包及其子包下面所有的类的所有方法的外部调用。

3.2.3 this

Spring Aop是基于代理的,this就表示代理对象。this类型的Pointcut表达式的语法是this(type),当生成的代理对象可以转换为type指定的类型时则表示匹配。基于JDK接口的代理和基于CGLIB的代理生成的代理对象是不一样的。

  • 1、“this(com.elim.spring.aop.service.IUserService)”匹配生成的代理对象是IUserService类型的所有方法的外部调用。

3.2.4 target

Spring Aop是基于代理的,target则表示被代理的目标对象。当被代理的目标对象可以被转换为指定的类型时则表示匹配。

  • 1、“target(com.elim.spring.aop.service.IUserService)”则匹配所有被代理的目标对象能够转换为IUserService类型的所有方法的外部调用。

3.2.5 args

args用来匹配方法参数的。

  • 1、“args()”匹配任何不带参数的方法。
  • 2、“args(java.lang.String)”匹配任何只带一个参数,而且这个参数的类型是String的方法。
  • 3、“args(..)”带任意参数的方法。
  • 4、“args(java.lang.String,..)”匹配带任意个参数,但是第一个参数的类型是String的方法。
  • 5、“args(..,java.lang.String)”匹配带任意个参数,但是最后一个参数的类型是String的方法。

3.2.6 @target

@target匹配当被代理的目标对象对应的类型及其父类型上拥有指定的注解时。

  • 1、“@target(com.elim.spring.support.MyAnnotation)”匹配被代理的目标对象对应的类型上拥有MyAnnotation注解时。

3.2.7 @args

@args匹配被调用的方法上含有参数,且对应的参数类型上拥有指定的注解的情况。

  • 1、“@args(com.elim.spring.support.MyAnnotation)”匹配方法参数类型上拥有MyAnnotation注解的方法调用。如我们有一个方法add(MyParam param)接收一个MyParam类型的参数,而MyParam这个类是拥有注解MyAnnotation的,则它可以被Pointcut表达式“@args(com.elim.spring.support.MyAnnotation)”匹配上。

3.2.8 @within

@within用于匹配被代理的目标对象对应的类型或其父类型拥有指定的注解的情况,但只有在调用拥有指定注解的类上的方法时才匹配。

  • 1、“@within(com.elim.spring.support.MyAnnotation)”匹配被调用的方法声明的类上拥有MyAnnotation注解的情况。比如有一个ClassA上使用了注解MyAnnotation标注,并且定义了一个方法a(),那么在调用ClassA.a()方法时将匹配该Pointcut;如果有一个ClassB上没有MyAnnotation注解,但是它继承自ClassA,同时它上面定义了一个方法b(),那么在调用ClassB().b()方法时不会匹配该Pointcut,但是在调用ClassB().a()时将匹配该方法调用,因为a()是定义在父类型ClassA上的,且ClassA上使用了MyAnnotation注解。但是如果子类ClassB覆写了父类ClassA的a()方法,则调用ClassB.a()方法时也不匹配该Pointcut。

3.2.9 @annotation

@annotation用于匹配方法上拥有指定注解的情况。

  • 1、“@annotation(com.elim.spring.support.MyAnnotation)”匹配所有的方法上拥有MyAnnotation注解的方法外部调用。

3.2.10 bean

bean用于匹配当调用的是指定的Spring的某个bean的方法时。

  • 1、“bean(abc)”匹配Spring Bean容器中id或name为abc的bean的方法调用。
  • 2、“bean(user*)”匹配所有id或name为以user开头的bean的方法调用。

3.3 表达式组合

表达式的组合其实就是对应的表达式的逻辑运算,与、或、非。可以通过它们把多个表达式组合在一起。

  • 1、“bean(userService) && args()”匹配id或name为userService的bean的所有无参方法。
  • 2、“bean(userService) || @annotation(MyAnnotation)”匹配id或name为userService的bean的方法调用,或者是方法上使用了MyAnnotation注解的方法调用。
  • 3、“bean(userService) && !args()”匹配id或name为userService的bean的所有有参方法调用。

3.4 基于Aspectj注解的Pointcut表达式应用

在使用基于Aspectj注解的Spring Aop时,我们可以把通过@Pointcut注解定义Pointcut,指定其表达式,然后在需要使用Pointcut表达式的时候直接指定Pointcut。

@Component
@Aspect
public class MyAspect {

	@Pointcut("execution(* add(..))")
	private void beforeAdd() {}
	
	@Before("beforeAdd()")
	public void before() {
		System.out.println("-----------before-----------");
	}
	
}

上面的代码中我们就是在@Before()中直接指定使用当前类定义的beforeAdd()方法对应的Pointcut的表达式,如果我们需要指定的Pointcut定义不是在当前类中的,我们需要加上类名称,如下面这个示例中引用的就是定义在MyService中的add()方法上的Pointcut的表达式。

@Before("com.elim.spring.aop.service.MyService.add()")
public void before2() {
	System.out.println("-----------before2-----------");
}

当然了,除了通过引用Pointcut定义间接的引用其对应的Pointcut表达式外,我们也可以直接使用Pointcut表达式的,如下面这个示例就直接在@Before中使用了Pointcut表达式。

/**
 * 所有的add方法的外部执行时
 */
@Before("execution(* add())")
public void beforeExecution() {
	System.out.println("-------------before execution---------------");
}

(注:本文是基于Spring4.1.0所写,写于2017年1月14日星期六)

目录
相关文章
|
3月前
|
XML 安全 Java
使用 Spring 的 @Aspect 和 @Pointcut 注解简化面向方面的编程 (AOP)
面向方面编程(AOP)通过分离横切关注点,如日志、安全和事务,提升代码模块化与可维护性。Spring 提供了对 AOP 的强大支持,核心注解 `@Aspect` 和 `@Pointcut` 使得定义切面与切入点变得简洁直观。`@Aspect` 标记切面类,集中处理通用逻辑;`@Pointcut` 则通过表达式定义通知的应用位置,提高代码可读性与复用性。二者结合,使开发者能清晰划分业务逻辑与辅助功能,简化维护并提升系统灵活性。Spring AOP 借助代理机制实现运行时织入,与 Spring 容器无缝集成,支持依赖注入与声明式配置,是构建清晰、高内聚应用的理想选择。
423 0
|
2月前
|
XML Java 数据格式
《深入理解Spring》:AOP面向切面编程深度解析
Spring AOP通过代理模式实现面向切面编程,将日志、事务等横切关注点与业务逻辑分离。支持注解、XML和编程式配置,提供五种通知类型及丰富切点表达式,助力构建高内聚、低耦合的可维护系统。
|
4月前
|
人工智能 监控 安全
如何快速上手【Spring AOP】?核心应用实战(上篇)
哈喽大家好吖~欢迎来到Spring AOP系列教程的上篇 - 应用篇。在本篇,我们将专注于Spring AOP的实际应用,通过具体的代码示例和场景分析,帮助大家掌握AOP的使用方法和技巧。而在后续的下篇中,我们将深入探讨Spring AOP的实现原理和底层机制。 AOP(Aspect-Oriented Programming,面向切面编程)是Spring框架中的核心特性之一,它能够帮助我们解决横切关注点(如日志记录、性能统计、安全控制、事务管理等)的问题,提高代码的模块化程度和复用性。
|
4月前
|
设计模式 Java 开发者
如何快速上手【Spring AOP】?从动态代理到源码剖析(下篇)
Spring AOP的实现本质上依赖于代理模式这一经典设计模式。代理模式通过引入代理对象作为目标对象的中间层,实现了对目标对象访问的控制与增强,其核心价值在于解耦核心业务逻辑与横切关注点。在框架设计中,这种模式广泛用于实现功能扩展(如远程调用、延迟加载)、行为拦截(如权限校验、异常处理)等场景,为系统提供了更高的灵活性和可维护性。
|
5月前
|
Java Spring 容器
SpringBoot自动配置的原理是什么?
Spring Boot自动配置核心在于@EnableAutoConfiguration注解,它通过@Import导入配置选择器,加载META-INF/spring.factories中定义的自动配置类。这些类根据@Conditional系列注解判断是否生效。但Spring Boot 3.0后已弃用spring.factories,改用新格式的.imports文件进行配置。
908 0
|
6月前
|
人工智能 Java 测试技术
Spring Boot 集成 JUnit 单元测试
本文介绍了在Spring Boot中使用JUnit 5进行单元测试的常用方法与技巧,包括添加依赖、编写测试类、使用@SpringBootTest参数、自动装配测试模块(如JSON、MVC、WebFlux、JDBC等),以及@MockBean和@SpyBean的应用。内容实用,适合Java开发者参考学习。
647 0
|
2月前
|
JavaScript Java Maven
【SpringBoot(二)】带你认识Yaml配置文件类型、SpringMVC的资源访问路径 和 静态资源配置的原理!
SpringBoot专栏第二章,从本章开始正式进入SpringBoot的WEB阶段开发,本章先带你认识yaml配置文件和资源的路径配置原理,以方便在后面的文章中打下基础
301 3
|
2月前
|
Java 测试技术 数据库连接
【SpringBoot(四)】还不懂文件上传?JUnit使用?本文带你了解SpringBoot的文件上传、异常处理、组件注入等知识!并且带你领悟JUnit单元测试的使用!
Spring专栏第四章,本文带你上手 SpringBoot 的文件上传、异常处理、组件注入等功能 并且为你演示Junit5的基础上手体验
849 2