必备技能:spring aop 切入点表达式,你都会么?

本文主要介绍spring aop中9种切入点表达式的写法

  • execute
  • within
  • this
  • target
  • args
  • @target
  • @within
  • @annotation
  • @args

1、execute表达式

拦截任意公共方法

execution(public * *(..))

拦截以set开头的任意方法

execution(* set*(..))

拦截类或者接口中的方法

execution(* com.xyz.service.AccountService.*(..))

拦截AccountService(类、接口)中定义的所有方法

拦截包中定义的方法,不包含子包中的方法

execution(* com.xyz.service.*.*(..))

拦截com.xyz.service包中所有类中任意方法,不包含子包中的类

拦截包或者子包中定义的方法

execution(* com.xyz.service..*.*(..))

拦截com.xyz.service包或者子包中定义的所有方法

2、within表达式

表达式格式:包名. 或者 包名..

拦截包中任意方法,不包含子包中的方法

within(com.xyz.service.*)

拦截service包中任意类的任意方法

拦截包或者子包中定义的方法

within(com.xyz.service..*)

拦截service包及子包中任意类的任意方法

3、this表达式

代理对象为指定的类型会被拦截

目标对象使用aop之后生成的代理对象必须是指定的类型才会被拦截,注意是目标对象被代理之后生成的代理对象和指定的类型匹配才会被拦截

this(com.xyz.service.AccountService)

示例
this表达式的使用,可能不是很好理解,用示例说明一下:


<?xml version="1.0" encoding="UTF-8"?>
<projectxmlns="http://maven.apache.org/POM/4.0." xmlns:xsi="http://www.w3.org/2001/XMLSchemainsance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.ms</groupId>
<artifactId>spring-aop-demo   </artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-aop-demo</name>
<description>Demo project for Spring Boot</description>

<properties>
<java.version>1.8</java.version>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

package com.ms.aop.jthis.demo1;

public interface IService {
void m1();
}

package com.ms.aop.jthis.demo1;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

@Slf4jbr/>@Component
public class ServiceImpl implements IService {br/>@Override
public void m1() {
log.info("切入点this测试!");
}
}

package com.ms.aop.jthis.demo1;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
br/>@Aspect
@Component
br/>@Slf4j
public class Interceptor1 {

@Pointcut("this(com.ms.aop.jthis.demo1.ServiceImpl)")
public void pointcut() {
}

@Around("pointcut()")
public Object invoke(ProceedingJoinPoint invocation) throws Throwable {
    log.info("方法执行之前");
    Object result = invocation.proceed();
    log.info("方法执行完毕");
    return result;
}

}

package com.ms.aop.jthis.demo1;

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@ComponentScan(basePackageClasses = {Client.class})br/>@EnableAspectJAutoProxy
@Slf4j
public class Client {
public static void main(String[] args) {
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(Client.class);
IService service = annotationConfigApplicationContext.getBean(IService.class);
service.m1();
log.info("{}", service instanceof ServiceImpl);
}
}

**执行结果**

10:27:12.277 [main] INFO com.ms.aop.jthis.demo1.ServiceImpl - 切入点this测试!
10:27:12.277 [main] INFO com.ms.aop.jthis.demo1.Client - false


1. **@EnableAspectJAutoProxy**:表示若spring创建的对象如果实现了接口,默认使用jdk动态代理,如果没有实现接口,使用cglib创建代理对象

2. 所以 **service** 是使用jdk动态代理生成的对象,**service instanceof ServiceImpl** 为 **false**

3. **@Pointcut("this(com.ms.aop.jthis.demo1.ServiceImpl)")**表示被spring代理之后生成的对象必须为**com.ms.aop.jthis.demo1.ServiceImpl**才会被拦截,但是**service**不是**ServiceImpl**类型的对象了,所以不会被拦截

4. 修改代码**@EnableAspectJAutoProxy(proxyTargetClass=true)**,使用cglib来生成代理对象

**执行结果:**

10:34:50.736[main]INFO com.ms.aop.jthis.demo1.Interceptor1-方法执行之前

10:34:50.755[main]INFO com.ms.aop.jthis.demo1.ServiceImpl-切入点this测试!

10:34:50.756[main]INFO com.ms.aop.jthis.demo1.Interceptor1-方法执行完毕

10:34:50.756[main]INFO com.ms.aop.jthis.demo1.Client-true

> service 为 ServiceImpl类型的对象,所以会被拦截

### **4、target表达式**

目标对象为指定的类型被拦截

target(com.xyz.service.AccountService)

> 目标对象为AccountService类型的会被代理

**示例**

package com.ms.aop.target;

public interface IService {
void m1();}

package com.ms.aop.target;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

@Slf4jbr/>@Component
public class ServiceImpl implements IService {
br/>@Override
public void m1() {
log.info("切入点target测试!");
}
}

package com.ms.aop.target;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Aspectbr/>@Component
@Slf4j
public class Interceptor1 {

@Pointcut("target(com.ms.aop.target.ServiceImpl)")
public void pointcut() {
}

@Around("pointcut()")
public Object invoke(ProceedingJoinPoint invocation) throws Throwable {
    log.info("方法执行之前");
    Object result = invocation.proceed();
    log.info("方法执行完毕");
    return result;
}

}

package com.ms.aop.target;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@ComponentScan(basePackageClasses = {Client.class})br/>@EnableAspectJAutoProxy
public class Client {
public static void main(String[] args) {
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(Client.class);
IService service = annotationConfigApplicationContext.getBean(IService.class);
service.m1();
}
}

**执行结果:**

10:49:01.674 [main] INFO com.ms.aop.targetInterceptor1 - 方法执行之前
10:49:01.674 [main] INFO com.ms.aop.target.ServiceImpl - 切入点target测试!
10:49:01.674 [main] INFO com.ms.aop.target.Interceptor1 - 方法执行完毕

**this 和 target 的不同点**
1. **this作用于代理对象,target作用于目标对象**
2. **this表示目标对象被代理之后生成的代理对象和指定的类型匹配会被拦截**,匹配的是代理对象
3. **target表示目标对象和指定的类型匹配会被拦截**,匹配的是目标对象

### **5、args 表达式**

匹配方法中的参数

@Pointcut("args(com.ms.aop.args.demo1.UserModel)")

> 匹配只有一个参数,且类型为**com.ms.aop.args.demo1.UserModel**

匹配多个参数

args(type1,type2,typeN)

匹配任意多个参数

@Pointcut("args(com.ms.aop.args.demo1.UserModel,..)")

匹配第一个参数类型为**com.ms.aop.args.demo1.UserModel**的所有方法, .. 表示任意个参数

### **6、@target表达式**

匹配的目标对象的类有一个指定的注解

@target(com.ms.aop.jtarget.Annotation1)

> 目标对象中包含**com.ms.aop.jtarget.Annotation1**注解,调用该目标对象的任意方法都会被拦截

### **7、@within表达式**

指定匹配必须包含某个注解的

@within(com.ms.aop.jwithin.Annotation1)

> 声明有**com.ms.aop.jwithin.Annotation1**注解的类中的所有方法都会被拦截

##### **@target 和 @within 的不同点**

1. **@target(注解A)**:判断被**调用的目标对象**中是否声明了注解A,如果有,会被拦截

2. **@within(注解A)**: 判断被**调用的方法所属的类**中是否声明了注解A,如果有,会被拦截

@target关注的是被调用的对象,@within关注的是调用的方法所在的类

### **8、@annotation表达式**
匹配有指定注解的方法(注解作用在方法上面)

@annotation(com.ms.aop.jannotation.demo2.Annotation1)

> 被调用的方法包含指定的注解

### **9、@args表达式**

方法参数所属的类型上有指定的注解,被匹配
> 注意:是**方法参数所属的类型**上有指定的注解,不是方法参数中有注解

- 匹配1个参数,且第1个参数所属的类中有Anno1注解

@args(com.ms.aop.jargs.demo1.Anno1)

- 匹配多个参数,且多个参数所属的类型上都有指定的注解

@args(com.ms.aop.jargs.demo1.Anno1,com.ms.aop.jargs.demo1.Anno2)

- 匹配多个参数,且第一个参数所属的类中有Anno1注解

@args(com.ms.aop.jargs.demo2.Anno1,..)

必备技能:spring aop 切入点表达式,你都会么?

原文地址:https://blog.51cto.com/14570694/2446938

时间: 2024-12-14 06:17:05

必备技能:spring aop 切入点表达式,你都会么?的相关文章

Spring AOP 切入点表达式使用

1.切入点表达式 1)匹配类型 用于匹配哪些类型的方法启用方面组件,语法格式如下 within(类型) --匹配容器中HibernateCostDaoImpl的所有方法 within(com.tarena.dao.HibernateCostDaoImpl) --匹配com.tarena包下所有类的所有方法 within(com.tarena.*) --匹配com.tarena包及子包的所有类的所有方法 within(com.tarena..*) 2)匹配方法 用于匹配哪些方法启用方面组件,语法格

spring aop execution表达式说明

在使用spring框架配置AOP的时候,不管是通过XML配置文件还是注解的方式都需要定义pointcut"切入点" 例如定义切入点表达式 execution(* com.sample.service.impl..*.*(..)) execution()是最常用的切点函数,其语法如下所示: 整个表达式可以分为五个部分: 1.execution(): 表达式主体. 2.第一个*号:表示返回类型,*号表示所有的类型. 3.包名:表示需要拦截的包名,后面的两个句点表示当前包和当前包的所有子包,

Spring的切入点表达式

@PointCut切入点表达式语法格式是:execution(访问权限 返回值类型 方法全限定名(参数类型列表)) 限定符: *: 1)匹配某全类名下,任意或多个方法: 表示匹配com.zdc.aop.Calculator下以a打头的任意方法.并且返回值和两个参数都是int类型. execution(public int com.zdc.aop.Calculator.a*(int, int))       表示匹配com.zdc.aop.Calculator下的任意方法.并且返回值和两个参数都是

AOP切入点表达式

任意公共方法的执行: execution(public * *(..)) 任何一个以“set”开始的方法的执行: execution(* set*(..)) AccountService 接口的任意方法的执行: execution(* com.xyz.service.AccountService.*(..)) 定义在service包里的任意方法的执行: execution(* com.xyz.service.*.*(..)) 定义在service包或者子包里的任意方法的执行: execution

Spring Aop 切点表达式

在Spring AOP 中,通常需要借助AspectJ 的切点表达式语言来定义切点.重要的是Spring 中仅支持AspectJ切点指示器的一个子集. Spring 支持的AspectJ的切点指示器 AspectJ 指示器 描述 args() 限制连接点匹配参数为执行类型的执行方法 @args() 限制连接点匹配参数由执行注解标注的执行方法 execution() 匹配连接点的执行方法 this() 限制连接点匹配AOP代理的Bean引用类型为指定类型的Bean target() 限制连接点匹配

Spring AOP切点表达式用法总结

1. 简介 面向对象编程,也称为OOP(即Object Oriented Programming)最大的优点在于能够将业务模块进行封装,从而达到功能复用的目的.通过面向对象编程,不同的模板可以相互组装,从而实现更为复杂的业务模块,其结构形式可用下图表示: 面向对象编程解决了业务模块的封装复用的问题,但是对于某些模块,其本身并不独属于摸个业务模块,而是根据不同的情况,贯穿于某几个或全部的模块之间的.例如登录验证,其只开放几个可以不用登录的接口给用户使用(一般登录使用拦截器实现,但是其切面思想是一致

Java进阶知识22 Spring execution 切入点表达式

1.概述   切入点(execution ):可以对指定的方法进行拦截,从而给指定的类生成代理对象.(拦截谁,就是在谁那里切入指定的程序/方法) 格式: execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern) throws-pattern?) 参数解析: modifiers-pattern?:指定方法的修饰符,支持通配符,该部分可以省略.(public/pr

spring AOP excution表达式各符号意思

execution(*com.sample.service.impl..*.*(..)) 符号 含义 execution() 表达式的主题 第一个"*"符号 表示返回值的类型任意: com.sample.service.impl AOP所切的服务的包名 包名后面的".." 表示当前包及子包 第二个"*" 表示类名,*即所有类.可自定义 .*(..) 表示任何方法名,括号表示参 数,两个点表示任何参数类型 原文地址:https://www.cnbl

使用注解匹配Spring Aop切点表达式

Spring中的类基本都会标注解,所以使用注解匹配切点可以满足绝大部分需求 主要使用@within()/@target @annotaton() @args()等... 匹配@Service类中的所有方法: @within(org.springframework.stereotype.Service) 或 @target(org.springframework.stereotype.Service) 匹配标注了@RequestMapping的所有方法 @annotation(org.spring