溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

必備技能:spring aop 切入點(diǎn)表達(dá)式,你都會(huì)么?

發(fā)布時(shí)間:2020-08-01 13:52:17 來源:網(wǎng)絡(luò) 閱讀:234 作者:wx5d9ed7c8443c3 欄目:編程語言

本文主要介紹spring aop中9種切入點(diǎn)表達(dá)式的寫法

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

1、execute表達(dá)式

攔截任意公共方法

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表達(dá)式

表達(dá)式格式:包名. 或者 包名..

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

within(com.xyz.service.*)

攔截service包中任意類的任意方法

攔截包或者子包中定義的方法

within(com.xyz.service..*)

攔截service包及子包中任意類的任意方法

3、this表達(dá)式

代理對(duì)象為指定的類型會(huì)被攔截

目標(biāo)對(duì)象使用aop之后生成的代理對(duì)象必須是指定的類型才會(huì)被攔截,注意是目標(biāo)對(duì)象被代理之后生成的代理對(duì)象和指定的類型匹配才會(huì)被攔截

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>

<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("切入點(diǎn)this測(cè)試!");
}
}

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測(cè)試!
10:27:12.277 [main] INFO com.ms.aop.jthis.demo1.Client - false


1. **@EnableAspectJAutoProxy**:表示若spring創(chuàng)建的對(duì)象如果實(shí)現(xiàn)了接口,默認(rèn)使用jdk動(dòng)態(tài)代理,如果沒有實(shí)現(xiàn)接口,使用cglib創(chuàng)建代理對(duì)象

2. 所以 **service** 是使用jdk動(dòng)態(tài)代理生成的對(duì)象,**service instanceof ServiceImpl** 為 **false**

3. **@Pointcut("this(com.ms.aop.jthis.demo1.ServiceImpl)")**表示被spring代理之后生成的對(duì)象必須為**com.ms.aop.jthis.demo1.ServiceImpl**才會(huì)被攔截,但是**service**不是**ServiceImpl**類型的對(duì)象了,所以不會(huì)被攔截

4. 修改代碼**@EnableAspectJAutoProxy(proxyTargetClass=true)**,使用cglib來生成代理對(duì)象

**執(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測(cè)試!

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類型的對(duì)象,所以會(huì)被攔截

### **4、target表達(dá)式**

目標(biāo)對(duì)象為指定的類型被攔截

target(com.xyz.service.AccountService)

> 目標(biāo)對(duì)象為AccountService類型的會(huì)被代理

**示例**

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測(cè)試!");
}
}

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測(cè)試!
10:49:01.674 [main] INFO com.ms.aop.target.Interceptor1 - 方法執(zhí)行完畢

**this 和 target 的不同點(diǎn)**
1. **this作用于代理對(duì)象,target作用于目標(biāo)對(duì)象**
2. **this表示目標(biāo)對(duì)象被代理之后生成的代理對(duì)象和指定的類型匹配會(huì)被攔截**,匹配的是代理對(duì)象
3. **target表示目標(biāo)對(duì)象和指定的類型匹配會(huì)被攔截**,匹配的是目標(biāo)對(duì)象

### **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)對(duì)象的類有一個(gè)指定的注解

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

> 目標(biāo)對(duì)象中包含**com.ms.aop.jtarget.Annotation1**注解,調(diào)用該目標(biāo)對(duì)象的任意方法都會(huì)被攔截

### **7、@within表達(dá)式**

指定匹配必須包含某個(gè)注解的

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

> 聲明有**com.ms.aop.jwithin.Annotation1**注解的類中的所有方法都會(huì)被攔截

##### **@target 和 @within 的不同點(diǎn)**

1. **@target(注解A)**:判斷被**調(diào)用的目標(biāo)對(duì)象**中是否聲明了注解A,如果有,會(huì)被攔截

2. **@within(注解A)**: 判斷被**調(diào)用的方法所屬的類**中是否聲明了注解A,如果有,會(huì)被攔截

@target關(guān)注的是被調(diào)用的對(duì)象,@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,..)

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI