使用Java反射在Scala中获取方面中具有特定注释的方法参数

问题描述:

我正在使用aspectjscala中使用aop.我有方法

I am using aop in scala using aspectj. I have a method

def delete(@Id id:Long, name:String)

如何在我的外观文件中获取id的值.

How can I get the value of id in my aspect file.

@Around("execution (* com.myapp.Employee.delete(..))")   
def message(joinPoint: ProceedingJoinPoint): Object = {    
  val methodSignature =joinPoint.getSignature.asInstanceOf[MethodSignature] 
  //get the value of the field id
  joinPoint.proceed   
}

我无法获取这些值.

如果我尝试

val res = methodSignature.getMethod.getParameterAnnotations
res.map(annotations => println("size = "+annotations.length))

始终将尺寸打印为0.

现在我可以正确获取尺寸了.该方法在object中.但是我认为java反射读取object时存在一些问题.我改为class,现在可以获取注释了.但是如何获取带有该注释的参数?

Now I am getting the size correctly. The method was in object. But I think there are some problems with java reflection to read object. I changed to class and now able to get the annotations. But how can I get the parameter which is annotated with that annotation?

以下是一些Java示例代码,显示了如何获取方法注释以及参数注释以及参数类型(参数名称不可用 cchantep 已提及).我想您可以轻松地将其自己转换为Scala.

Here is some Java sample code showing how to get method annotations and also parameter annotations along with paramater types (parameter names are unavailable as cchantep already mentioned). I guess you can easily convert it into Scala by yourself.

package de.scrum_master.aspect;

import java.lang.annotation.Annotation;

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

@Aspect
public class MyAspect {
    @Before("execution (* com.myapp.Employee.delete(..))")
    public void myAdvice(JoinPoint joinPoint) throws Throwable {
        System.out.println(joinPoint);
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        String methodName = signature.getMethod().getName();
        Class<?>[] parameterTypes = signature.getMethod().getParameterTypes();

        System.out.println("Method annotations:");
        Annotation[] methodAnnotations = joinPoint.getTarget().getClass().getMethod(methodName, parameterTypes).getAnnotations();
        for (Annotation annotation : methodAnnotations)
            System.out.println("  " + annotation);

        System.out.println("Parameter annotations:");
        Annotation[][] parameterAnnotations = joinPoint.getTarget().getClass().getMethod(methodName, parameterTypes).getParameterAnnotations();
        int parameterIndex = 0;
        for (Annotation[] annotationsPerParameter : parameterAnnotations) {
            System.out.println("  Parameter of type " + parameterTypes[parameterIndex++].getName() + ":");
            for (Annotation annotation : annotationsPerParameter)
                System.out.println("    " + annotation);
        }
    }
}


更新:

好吧,在Java 8中,有一种确定参数名称的方法(如果您使用-parameters选项编译类).如果您使用Java 8 JRE/JDK,则Eclipse中还有一个针对此的编译器开关:

Well, in Java 8 there is a way to determine parameter names if you compile your classes with the -parameters option. There is also a compiler switch in Eclipse for that if you use a Java 8 JRE/JDK:

您还应该使用兼容Java 8的AspectJ版本,例如当前的1.8.5.然后您的外观如下所示:

You should also use a Java 8-compliant AspectJ version such as the current 1.8.5. Then your aspect can look as follows:

package de.scrum_master.aspect;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;

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

@Aspect
public class MyAspect {
    @Before("execution(!static * *..Application.*(..))")
    public void myAdvice(JoinPoint joinPoint) throws Throwable {
        System.out.println(joinPoint);
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        Parameter[] parameters = method.getParameters();

        System.out.println("Method annotations:");
        Annotation[] methodAnnotations = method.getAnnotations();
        for (Annotation annotation : methodAnnotations)
            System.out.println("  " + annotation);

        System.out.println("Parameter annotations:");
        for (Parameter parameter : parameters) {
            System.out.println("  " + parameter.getType().getName() + " " + parameter.getName());
            for (Annotation annotation : parameter.getAnnotations())
                System.out.println("    " + annotation);
        }
    }
}