您好,登錄后才能下訂單哦!
本文主要介紹spring aop中9種切入點表達式的寫法
攔截任意公共方法
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包或者子包中定義的所有方法
表達式格式:包名. 或者 包名..
攔截包中任意方法,不包含子包中的方法
within(com.xyz.service.*)
攔截service包中任意類的任意方法
攔截包或者子包中定義的方法
within(com.xyz.service..*)
攔截service包及子包中任意類的任意方法
代理對象為指定的類型會被攔截
目標對象使用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;
@Slf4j@Component
br/>@Component
br/>@Override
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;@Aspect
br/>@Aspect
br/>@Slf4j
@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})@EnableAspectJAutoProxy
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();
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;
@Slf4j@Component
br/>@Component
br/>@Override
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;
@Aspect@Component
br/>@Component
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})@EnableAspectJAutoProxy
br/>@EnableAspectJAutoProxy
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,..)
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。