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

Sea*_*oyd 28 java aop spring aspectj pointcut

我有一个在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
   }
}
Run Code Online (Sandbox Code Playgroud)

我还有以下方面定义:

/**
 * 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());
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

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

<aop:aspectj-autoproxy proxy-target-class="false" />

<bean class="com.mycompany.aspect.MyAspect">
    <property name="userService" ref="userService" />
</bean>
Run Code Online (Sandbox Code Playgroud)

Esp*_*pen 31

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

我建议你换掉:

execution(public * com.mycompany.myserviceimpl.*(..))
Run Code Online (Sandbox Code Playgroud)

有:

execution(public * com.mycompany.myservice.MyService+.*(..))
Run Code Online (Sandbox Code Playgroud)

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

我希望它有所帮助!


小智 5

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

execution(public * com.mycompany.myservice.MyService+.*(..))
Run Code Online (Sandbox Code Playgroud)

但是,如果我希望对* com.mycompany.services。**包中的所有服务都采用这种行为,该怎么办?

  • 这工作正常: execution(public * com.mycompany.myservice.*+.*(..)) (2认同)