java Spring AOP:如何获取被通知方法的注解

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2559255/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 21:47:08  来源:igfitidea点击:

Spring AOP: how to get the annotations of the adviced method

javasecurityspringspring-aop

提问by hugri

I'd like to implement declarative security with Spring/AOP and annotations. As you see in the next code sample I have the Restricted Annotations with the paramter "allowedRoles" for defining who is allowed to execute an adviced method.

我想用 Spring/AOP 和注释来实现声明式安全。正如您在下一个代码示例中看到的,我有带有参数“allowedRoles”的受限注释,用于定义允许执行建议方法的人员。

    @Restricted(allowedRoles="jira-administrators")
        public void setPassword(...) throws UserMgmtException {             
               // set password code
               ...
        }

Now, the problem is that in my Advice I have no access to the defined Annotations:

现在,问题是在我的 Advice 中,我无法访问定义的 Annotations:

public Object checkPermission(ProceedingJoinPoint pjp) throws Throwable {

    Signature signature = pjp.getSignature();
    System.out.println("Allowed:" + rolesAllowedForJoinPoint(pjp));
            ...
}

private Restricted rolesAllowedForJoinPoint(ProceedingJoinPoint thisJoinPoint)
        {
            MethodSignature methodSignature = (MethodSignature) thisJoinPoint.getSignature();
            Method targetMethod = methodSignature.getMethod();

            return targetMethod.getAnnotation(Restricted.class);
        }

The method above always returns null (there are no annotations found at all). Is there a simple solution to this?

上面的方法总是返回null(根本找不到注释)。有没有简单的解决方案?

I read something about using the AspectJ agent but I would prefer not to use this agent.

我读了一些关于使用 AspectJ 代理的内容,但我不想使用这个代理。

采纳答案by Bozho

I assume @Restrictedis your annotation. If that is the case, make sure you have:

我假设@Restricted是你的注释。如果是这种情况,请确保您拥有:

@Retention(RetentionPolicy.RUNTIME)

in your annotation definition. This means that the annotation is retained at runtime.

在您的注释定义中。这意味着注释在运行时保留。

回答by Oleg

To whoever is still having problem afterchanging annotation retention to Runtime, you might be having the same problem I had: getMethod() returns interface method instead of the implementing class. So, if you have your annotations in the class then naturally getAnnotations() on the interface method returns null.

对于将注释保留更改为运行时仍有问题的人,您可能遇到了与我相同的问题:getMethod() 返回接口方法而不是实现类。因此,如果您在类中有注释,那么接口方法上的 getAnnotations() 自然会返回 null。

The following solution solved this problem:

以下解决方案解决了这个问题:

final String methodName = pjp.getSignature().getName();
final MethodSignature methodSignature = (MethodSignature)pjp.getSignature();
Method method = methodSignature.getMethod();
if (method.getDeclaringClass().isInterface()) {
    method = pjp.getTarget().getClass().getDeclaredMethod(methodName, method.getParameterTypes());    
}

and if you like, you have the option of handling interface annotations here too.

如果您愿意,您也可以选择在此处处理界面注释。

Some more comments available here: getting template method instance from ProceedingJoinPoint

此处提供更多评论: 从 ProceedingJoinPoint 获取模板方法实例

Oleg

奥列格

回答by Ryan K

Even after changing the retention policy like Bozho mentioned this call to get annotation returns null:

即使像 Bozho 提到的那样更改保留策略之后,获取注释的调用也会返回 null:

targetMethod.getAnnotation(Restricted.class);

What I found is you have to bind the annotation. Given the interface is declared like this:

我发现你必须绑定注释。鉴于接口声明如下:

 @Retention(RetentionPolicy.RUNTIME)
 public @interface Restricted {
     String[] allowedRoles();
  }

The advice would need to be declared like this:

该建议需要像这样声明:

       @Before("@annotation( restrictedAnnotation )")
       public Object processRequest(final ProceedingJoinPoint pjp, Restricted restrictedAnnotation) throws Throwable {
                  String[] roles = restrictedAnnotation.allowedRoles();
                  System.out.println("Allowed:" +  roles);
       }

What this does is bind the annotation to the parameter in the method signature, restrictedAnnotation. The part I am not sure about is how it gets the annotation type, it seems to be based on the parameter. And once you have the annotation you can get the values.

这样做是将注释绑定到方法签名中的参数,restrictedAnnotation。我不确定的部分是它如何获取注释类型,它似乎是基于参数的。一旦你有了注释,你就可以获得值。

回答by LordEru

Whith Spring AOP if you have a situation like MyManagerImpl implements MyManagerthe pointcut is applied to the interfacemethod so MethodSignaturedescribes the method defined on MyManagerthat doesn't have any annotation. the only way I've found to fix this is to inspect the class of the jp.getTarget()object and retrieve the corresponding method.

如果您有MyManagerImpl implements MyManager切入点应用于interface方法的情况,那么 Spring AOPMethodSignature将描述定义在其上的方法MyManager没有任何注释。我发现解决这个问题的唯一方法是检查jp.getTarget()对象的类并检索相应的方法。

回答by dakull

Why don't you just use Spring Security? It's a brief to implement and use, I don't really see the point in wasting time reinventing the wheel.

为什么不直接使用Spring Security?这是实施和使用的简要说明,我真的不认为浪费时间重新发明轮子有什么意义。