为什么 AOP 在我的 Spring Boot 项目中不起作用?它从不执行@Around 注释的方法

Why AOP is not working in my Spring Boot project? It never execute the @Around annoted method

我试图按照此视频教程将 AOP 添加到我的 Spring 引导项目以执行日志操作:https://www.youtube.com/watch?v=RVvKPP5HyaA

但是它不工作,它没有记录任何东西。

所以这是我的 pom.xml 文件:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://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.5.6</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.easydefi</groupId>
    <artifactId>GET-USER-WS</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>GET-USER-WS</name>
    <description>Microservice that retrieves users from DB</description>
    <properties>
        <java.version>11</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        

        
        <!-- Validation -->
        <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>
        
        <!-- Security -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        
        <!-- JWT -->
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.1</version>
        </dependency>
        
        <!-- Lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.22</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-boot-starter</artifactId>
            <version>3.0.0</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>3.0.0</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
        </dependency>

        <dependency>
            <groupId>org.modelmapper</groupId>
            <artifactId>modelmapper</artifactId>
            <version>3.0.0</version>
        </dependency>
        
        <dependency>
            <groupId>nl.martijndwars</groupId>
            <artifactId>web-push</artifactId>
            <version>5.1.1</version>
        </dependency>
        
        <dependency>
          <groupId>org.bouncycastle</groupId>
          <artifactId>bcprov-jdk15on</artifactId>
          <version>1.68</version>
        </dependency>
        
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
            <version>2.6.3</version>
        </dependency>
        
        
     

    </dependencies>

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

</project>

如您所见,我向其添加了以下依赖项:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
    <version>2.6.3</version>
</dependency>

然后我创建了这个 LoggingAOP class 以配置 AOP 行为:

package com.easydefi.aop.logging;

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;

import com.fasterxml.jackson.databind.ObjectMapper;

import lombok.extern.java.Log;

@Aspect
@Component
@Log
public class LoggingAOP {
    
    @Pointcut(value = "execution(* com.easydefi.users.*.*.*(..))")
    public void myPointcut() {
        
    }
    
    @Around("myPointcut()")
    public Object applicationLogger(ProceedingJoinPoint pjp) throws Throwable {
        
        ObjectMapper mapper = new ObjectMapper();
        
        String methodName = pjp.getSignature().getName();
        String className = pjp.getTarget().getClass().toString();
        
        Object[] argsArray = pjp.getArgs();
        
        log.info("Method invoked " + className + ":" + methodName + "() arguments: " + mapper.writeValueAsString(argsArray));
        
        Object response = pjp.proceed();
        
        log.info(className + ":" + methodName + "() Response: " + mapper.writeValueAsString(response));
        
        return response;
        
    }

}

理论上使用的@Pointcut表达式:

@Pointcut(value = "execution(* com.easydefi.users.*.*.*(..))")

应该将所有方法的执行定义到项目根目录中定义的所有包的所有 class 中,即 com.easydefi.users 但它没有记录任何内容。

运行 我的应用程序并调用控制器方法或服务方法 我预计他会进入 applicationLogger() 方法。但它不起作用(我也在调试模式下尝试过,但它从未进入此方法)。

这是我的项目结构:

所以怎么了?我错过了什么?我该如何尝试修复它?

你的切入点

execution(* com.easydefi.users.*.*.*(..))

看起来有点不灵活,但它非常适合像

这样的拦截方法
public void com.easydefi.users.service.CoinService.doSomething()
public boolean com.easydefi.users.specification.MySpec.fooBar(int, String)

不适用于

public String com.easydefi.users.specification.criteria.MyCriteria.zot()
public void com.easydefi.users.aa.bb.cc.SomeService.zot()

原因 M。 Deinum 已经提到了。他建议使用 ..* 表示法,意思是“..* 前面的包中任何 class 中的任何方法”,完全正确:

execution(* com.easydefi.users..*(..))

我还想强调,这个答案的功劳应该是他的,如果他喜欢简单地复制我的答案并 post 用他自己的名字而不是评论,我会删除这个一个高兴地代替。但我确实认为问题应该得到全面的回答。