在 Spring AOP 6.1+ 中访问 Groovy 类的方法参数名称时出现问题

问题描述 投票:0回答:1

自6.1 《参数名称保留

LocalVariableTableParameterNameDiscoverer 已在 6.1 中删除。”

即使在java编译器中使用-parameters,我们也无法再做这样的事情了

@CustomAnnotation(projectIdParameter = "projectId", userIdParameter = "#userEntity.id")
public ProjectEntity getProject(UserEntity userEntity, String projectId)

因为在@传入JoinPoint之前,我们以前可以这样做

joinPoint.getSignature().getParameterNames()

但是 getParameterNames() 不再可用,并且如果您将 getSignature 转换为 MethodSignature,getParameterNames 现在返回 null。

我们要做的就是将方面的功能放入之前注释的每个方法中。我们喜欢使用 AOP 来解决这些安全类型问题,但不确定如何让它适应 Spring 中的更改。

我们是否可以保留 AOP 方法?

spring groovy spring-aop jep-118
1个回答
1
投票

即使在 java 编译器中使用 -parameters,我们也不再能够做这样的事情......

那么你就做错了。无论是从 Maven 还是自动导入 Maven 项目并从 IntelliJ IDEA 运行时,这都可以正常工作:

<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 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.example</groupId>
  <artifactId>spring-boot-sample</artifactId>
  <version>1.0-SNAPSHOT</version>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <maven.compiler.source>8</maven.compiler.source>
    <maven.compiler.target>8</maven.compiler.target>
    <groovy.version>4.0.19</groovy.version>
  </properties>

  <build>
    <plugins>
      <plugin>
        <groupId>org.codehaus.gmavenplus</groupId>
        <artifactId>gmavenplus-plugin</artifactId>
        <version>3.0.2</version>
        <executions>
          <execution>
            <goals>
              <goal>execute</goal>
              <goal>addSources</goal>
              <goal>addTestSources</goal>
              <goal>generateStubs</goal>
              <goal>compile</goal>
              <goal>generateTestStubs</goal>
              <goal>compileTests</goal>
              <goal>removeStubs</goal>
              <goal>removeTestStubs</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <parameters>true</parameters>
          <verbose>true</verbose>
        </configuration>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.12.1</version>
        <configuration>
          <compilerArgs>
            <arg>-parameters</arg>
          </compilerArgs>
        </configuration>
      </plugin>
      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>exec-maven-plugin</artifactId>
        <version>3.2.0</version>
        <executions>
          <execution>
            <phase>verify</phase>
            <goals>
              <goal>java</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <mainClass>com.example.Application</mainClass>
        </configuration>
      </plugin>
    </plugins>
  </build>

  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter</artifactId>
      <version>3.2.3</version>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-aop</artifactId>
      <version>3.2.3</version>
    </dependency>
    <dependency>
      <groupId>org.apache.groovy</groupId>
      <artifactId>groovy</artifactId>
      <version>${groovy.version}</version>
    </dependency>
  </dependencies>

</project>
package com.example;

public @interface CustomAnnotation {
  String projectIdParameter();
  String userIdParameter();
}
package com.example;

import org.springframework.stereotype.Service;

@Service
public class SampleService {
  @CustomAnnotation(projectIdParameter = "projectId", userIdParameter = "#userEntity.id")
  public void doSomething(int foo, String bar, Object zot) {
    System.out.println("Doing something in service method");
  }
}
package com.example

import org.springframework.stereotype.Service

@Service
class GroovyService {
  @CustomAnnotation(projectIdParameter = "projectId", userIdParameter = "#userEntity.id")
  void doSomething(int foo, String bar, Object zot) {
    System.out.println("Doing something in Groovy service method")
  }
}
package com.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

@SpringBootApplication
public class Application {

  public static void main(String[] args) {
    try (ConfigurableApplicationContext applicationContext = SpringApplication.run(Application.class, args)) {
      applicationContext.getBean(SampleService.class).doSomething(11, "dummy", new Integer(42));
      applicationContext.getBean(GroovyService.class).doSomething(11, "dummy", new Integer(42));
    }
  }
}
package com.example;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.util.Arrays;

@Aspect
@Component
public class SampleAspect {
  @Before("@annotation(CustomAnnotation)")
  public void beforeServiceMethodExecution(JoinPoint joinPoint) {
    System.out.println(joinPoint);
    System.out.println(
      Arrays.toString(
        ((MethodSignature) joinPoint.getSignature()).getParameterNames()
      )
    );
  }
}

控制台日志:

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v3.2.3)

2024-03-09T14:53:30.327+01:00  INFO 14188 --- [           main] com.example.Application                  : Starting Application using Java 21 with PID 14188 (C:\Users\Alexander\Documents\java-src\SO_AJ_Spring61ParameterNames_78129715\target\classes started by Alexander in C:\Users\Alexander\Documents\java-src\SO_AJ_Spring61ParameterNames_78129715)
2024-03-09T14:53:30.329+01:00  INFO 14188 --- [           main] com.example.Application                  : No active profile set, falling back to 1 default profile: "default"
2024-03-09T14:53:31.201+01:00  INFO 14188 --- [           main] com.example.Application                  : Started Application in 1.193 seconds (process running for 1.734)
execution(void com.example.SampleService.doSomething(int,String,Object))
[foo, bar, zot]
Doing something in service method
execution(void com.example.GroovyService.doSomething(int,String,Object))
[foo, bar, zot]
Doing something in Groovy service method

Spring Boot 3.2.3、Spring 6.1.4、JDK 21、Groovy 4.0.19。

© www.soinside.com 2019 - 2024. All rights reserved.