web-dev-qa-db-ja.com

インターフェースの注釈と一致するSpring AOPポイントカット

Java 6/Spring 3に実装されているサービスクラスがあり、役割によってアクセスを制限するための注釈が必要です。

OperationTypeと呼ばれる列挙型からの1つ以上の値を値属性として持つRequiredPermissionと呼ばれる注釈を定義しました:

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では、アスペクトがアノテーション1つのインターフェースメソッド(トランザクションなど)によってトリガーされる場合があることを知っています。ここに特別な構文はありますか?.

PS:私は自分の春の設定を投稿していません。問題なく動作しているようです。いいえ、それらは私の元のクラスでもメソッド名でもありません。

PPS:実際、これは私の春の構成の関連部分です:

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

<bean class="com.mycompany.aspect.MyAspect">
    <property name="userService" ref="userService" />
</bean>
28

私があなたの正解を理解している場合、MyServiceを拡張し、注釈が付けられ、優先引数が指定されているクラス内のすべてのメソッドを見つけるポイントカットが必要です。

交換することをお勧めします:

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

と:

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

ジョインポイントをMyServiceクラスまたはそれを拡張するクラスと一致させる場合は、プラス記号を使用します。

お役に立てば幸いです。

31
Espen

エスペン、あなたのコードは1つのクラスでのみ機能します:

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

しかし、* com.mycompany.services。**パッケージのすべてのサービスに対してこの動作が必要な場合はどうなりますか?

4
pkmk