【问题标题】:Why AOP is not working in my Spring Boot project? It never execute the @Around annoted method为什么 AOP 在我的 Spring Boot 项目中不起作用?它从不执行 @Around 注释方法
【发布时间】:2022-02-08 23:23:44
【问题描述】:

我正在尝试按照此视频教程将 AOP 添加到我的 Spring Boot 项目中以执行日志操作: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 类来配置 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.*.*.*(..))")

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

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

这是我的项目结构:

那么有什么问题吗?我错过了什么?我该如何尝试修复它?

【问题讨论】:

  • 您的项目继承自spring-boot-starter-parent:2.5.6,但您包含了依赖项spring-boot-starter-aop:2.6.3。你通常会省略版本,让 Spring Boot 依赖管理引入适当的 starter 版本。
  • 这个表达式并不像你想象的那样。相反,您应该编写类似execution(* com.easydefi.users..*(..)) 的内容,这确实意味着包和子包中的所有方法。

标签: java spring spring-boot aop spring-aop


【解决方案1】:

你的切入点

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 已经提到过。他建议使用..* 表示法,意思是“包中任何类中的任何方法都以..* 开头”,这是完全正确的:

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

我还想强调,这个答案的功劳应该是他的,如果他喜欢简单地复制我的答案并以他自己的名义发布而不是仅仅发表评论,我会很乐意删除这个答案。但我确实认为问题应该得到全面的答案。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-07-03
    • 2016-12-15
    • 2023-03-31
    • 1970-01-01
    • 1970-01-01
    • 2018-10-27
    • 1970-01-01
    相关资源
    最近更新 更多