Spring AOP切入点与接口上的注释匹配

我有一个在Java 6 / Spring 3中实现的服务类,它需要一个注释来限制角色访问。

我已经定义了一个名为RequiredPermission的注释,它具有一个名为OperationType的枚举中的一个或多个值作为其value属性:

public @interface RequiredPermission { /** * One or more {@link OperationType}s that map to the permissions required * to execute this method. * * @return */ OperationType[] value();} public enum OperationType { TYPE1, TYPE2; } package com.mycompany.myservice; public interface MyService{ @RequiredPermission(OperationType.TYPE1) void myMethod( MyParameterObject obj ); } package com.mycompany.myserviceimpl; public class MyServiceImpl implements MyService{ public myMethod( MyParameterObject obj ){ // do stuff here } } 

我还有以下方面定义:

 /** * Security advice around methods that are annotated with * {@link RequiredPermission}. * * @param pjp * @param param * @param requiredPermission * @return * @throws Throwable */ @Around(value = "execution(public *" + " com.mycompany.myserviceimpl.*(..))" + " && args(param)" + // parameter object " && @annotation( requiredPermission )" // permission annotation , argNames = "param,requiredPermission") public Object processRequest(final ProceedingJoinPoint pjp, final MyParameterObject param, final RequiredPermission requiredPermission) throws Throwable { if(userService.userHasRoles(param.getUsername(),requiredPermission.values()){ return pjp.proceed(); }else{ throw new SorryButYouAreNotAllowedToDoThatException( param.getUsername(),requiredPermission.value()); } } 

参数对象包含用户名,我想在允许访问方法之前查找用户所需的角色。

当我将注释放在MyServiceImpl中的方法上时,一切正常,切入点匹配并且方面启动。但是,我认为注释是服务契约的一部分,应该在单独的API包中与接口一起发布。 显然,我不想将注释放在服务定义和实现(DRY)上。

我知道在Spring AOP中有一些情况,其中方面是由一个接口方法(例如Transactional)的注释触发的。 这里是否有特殊的语法,或者只是开箱即用。

PS:我没有发布我的弹簧配置,因为它似乎工作得很好。 不,这些既不是我的原始类,也不是方法名。

PPS:实际上,这是我的spring配置的相关部分:

     

如果我理解你是正确的,你需要一个切入点来查找扩展MyService的类中的所有方法,并使用首选参数进行注释。

我建议你换掉:

 execution(public * com.mycompany.myserviceimpl.*(..)) 

有:

 execution(public * com.mycompany.myservice.MyService+.*(..)) 

如果希望连接点与MyService类或扩展它的类匹配,则使用加号。

我希望它有所帮助!

Espen,您的代码仅适用于一个类:

 execution(public * com.mycompany.myservice.MyService+.*(..)) 

但是,如果我想在* com.mycompany.services。**包中的所有服务中使用此行为怎么办?

我遇到了同样的问题,但上面的建议没有帮助。 如果我只将其作为切入点:

 execution(public * com.mycompany.myservice.MyService+.*(..)) 

然后调用建议。 但是,如果我添加这个:

  && @annotation(xyzLogged) 

然后不会调用建议。 MyService接口在其某个方法上包含@Logged注释,甚至包含其类型声明。

您应该将@Inherited注释添加到@RequiredPermission注释中。

http://download.oracle.com/javase/6/docs/api/java/lang/annotation/Inherited.html