本文主要介紹spring aop中9種切入點(diǎn)表達(dá)式的寫法
成都創(chuàng)新互聯(lián)公司專注為客戶提供全方位的互聯(lián)網(wǎng)綜合服務(wù),包含不限于網(wǎng)站設(shè)計(jì)、成都網(wǎng)站制作、松溪網(wǎng)絡(luò)推廣、成都小程序開發(fā)、松溪網(wǎng)絡(luò)營銷、松溪企業(yè)策劃、松溪品牌公關(guān)、搜索引擎seo、人物專訪、企業(yè)宣傳片、企業(yè)代運(yùn)營等,從售前售中售后,我們都將竭誠為您服務(wù),您的肯定,是我們最大的嘉獎;成都創(chuàng)新互聯(lián)公司為所有大學(xué)生創(chuàng)業(yè)者提供松溪建站搭建服務(wù),24小時(shí)服務(wù)熱線:028-86922220,官方網(wǎng)址:www.cdcxhl.com
攔截任意公共方法
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包或者子包中定義的所有方法
表達(dá)式格式:包名. 或者 包名..
攔截包中任意方法,不包含子包中的方法
within(com.xyz.service.*)
攔截service包中任意類的任意方法
攔截包或者子包中定義的方法
within(com.xyz.service..*)
攔截service包及子包中任意類的任意方法
代理對象為指定的類型會被攔截
目標(biāo)對象使用aop之后生成的代理對象必須是指定的類型才會被攔截,注意是目標(biāo)對象被代理之后生成的代理對象和指定的類型匹配才會被攔截
this(com.xyz.service.AccountService)
示例
this表達(dá)式的使用,可能不是很好理解,用示例說明一下:<?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>
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("切入點(diǎn)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("方法執(zhí)行之前");
Object result = invocation.proceed();
log.info("方法執(zhí)行完畢");
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);
}
}
**執(zhí)行結(jié)果**
10:27:12.277 [main] INFO com.ms.aop.jthis.demo1.ServiceImpl - 切入點(diǎn)this測試!
10:27:12.277 [main] INFO com.ms.aop.jthis.demo1.Client - false
1. **@EnableAspectJAutoProxy**:表示若spring創(chuàng)建的對象如果實(shí)現(xiàn)了接口,默認(rèn)使用jdk動態(tài)代理,如果沒有實(shí)現(xiàn)接口,使用cglib創(chuàng)建代理對象
2. 所以 **service** 是使用jdk動態(tài)代理生成的對象,**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來生成代理對象
**執(zhí)行結(jié)果:**
10:34:50.736[main]INFO com.ms.aop.jthis.demo1.Interceptor1-方法執(zhí)行之前
10:34:50.755[main]INFO com.ms.aop.jthis.demo1.ServiceImpl-切入點(diǎn)this測試!
10:34:50.756[main]INFO com.ms.aop.jthis.demo1.Interceptor1-方法執(zhí)行完畢
10:34:50.756[main]INFO com.ms.aop.jthis.demo1.Client-true
> service 為 ServiceImpl類型的對象,所以會被攔截
### **4、target表達(dá)式**
目標(biāo)對象為指定的類型被攔截
target(com.xyz.service.AccountService)
> 目標(biāo)對象為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("切入點(diǎn)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("方法執(zhí)行之前");
Object result = invocation.proceed();
log.info("方法執(zhí)行完畢");
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();
}
}
**執(zhí)行結(jié)果:**
10:49:01.674 [main] INFO com.ms.aop.targetInterceptor1 - 方法執(zhí)行之前
10:49:01.674 [main] INFO com.ms.aop.target.ServiceImpl - 切入點(diǎn)target測試!
10:49:01.674 [main] INFO com.ms.aop.target.Interceptor1 - 方法執(zhí)行完畢
**this 和 target 的不同點(diǎn)**
1. **this作用于代理對象,target作用于目標(biāo)對象**
2. **this表示目標(biāo)對象被代理之后生成的代理對象和指定的類型匹配會被攔截**,匹配的是代理對象
3. **target表示目標(biāo)對象和指定的類型匹配會被攔截**,匹配的是目標(biāo)對象
### **5、args 表達(dá)式**
匹配方法中的參數(shù)
@Pointcut("args(com.ms.aop.args.demo1.UserModel)")
> 匹配只有一個(gè)參數(shù),且類型為**com.ms.aop.args.demo1.UserModel**
匹配多個(gè)參數(shù)
args(type1,type2,typeN)
匹配任意多個(gè)參數(shù)
@Pointcut("args(com.ms.aop.args.demo1.UserModel,..)")
匹配第一個(gè)參數(shù)類型為**com.ms.aop.args.demo1.UserModel**的所有方法, .. 表示任意個(gè)參數(shù)
### **6、@target表達(dá)式**
匹配的目標(biāo)對象的類有一個(gè)指定的注解
@target(com.ms.aop.jtarget.Annotation1)
> 目標(biāo)對象中包含**com.ms.aop.jtarget.Annotation1**注解,調(diào)用該目標(biāo)對象的任意方法都會被攔截
### **7、@within表達(dá)式**
指定匹配必須包含某個(gè)注解的
@within(com.ms.aop.jwithin.Annotation1)
> 聲明有**com.ms.aop.jwithin.Annotation1**注解的類中的所有方法都會被攔截
##### **@target 和 @within 的不同點(diǎn)**
1. **@target(注解A)**:判斷被**調(diào)用的目標(biāo)對象**中是否聲明了注解A,如果有,會被攔截
2. **@within(注解A)**: 判斷被**調(diào)用的方法所屬的類**中是否聲明了注解A,如果有,會被攔截
@target關(guān)注的是被調(diào)用的對象,@within關(guān)注的是調(diào)用的方法所在的類
### **8、@annotation表達(dá)式**
匹配有指定注解的方法(注解作用在方法上面)
@annotation(com.ms.aop.jannotation.demo2.Annotation1)
> 被調(diào)用的方法包含指定的注解
### **9、@args表達(dá)式**
方法參數(shù)所屬的類型上有指定的注解,被匹配
> 注意:是**方法參數(shù)所屬的類型**上有指定的注解,不是方法參數(shù)中有注解
- 匹配1個(gè)參數(shù),且第1個(gè)參數(shù)所屬的類中有Anno1注解
@args(com.ms.aop.jargs.demo1.Anno1)
- 匹配多個(gè)參數(shù),且多個(gè)參數(shù)所屬的類型上都有指定的注解
@args(com.ms.aop.jargs.demo1.Anno1,com.ms.aop.jargs.demo1.Anno2)
- 匹配多個(gè)參數(shù),且第一個(gè)參數(shù)所屬的類中有Anno1注解
@args(com.ms.aop.jargs.demo2.Anno1,..)