インターフェイス上の注釈と一致するスプリングAOPポイントカット
質問
Java 6 / Spring 3に実装されたサービスクラスがあり、役割によるアクセスを制限するための注釈が必要です。
OperationTypeと呼ばれる列挙から1つ以上の値を属性として属する必要があるexagePermissionと呼ばれる注釈を定義しました。
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パッケージで公開されるべきだと思います。 。そして明らかに、私はサービスの定義と実装の両方に注釈を置きたくありません(ドライ)。
Spring AOPには、アノテーションが1つのインターフェイスメソッド(トランザクションなど)によってトリガーされる場合があります。ここに特別な構文はありますか、それとも箱から出してはまったく不可能です。
PS:Spring Configは正常に機能しているようです。いいえ、それらは私の元のクラスでもメソッド名でもありません。
PPS:実際、ここに私のスプリング構成の関連部分があります:
<aop:aspectj-autoproxy proxy-target-class="false" />
<bean class="com.mycompany.aspect.MyAspect">
<property name="userService" ref="userService" />
</bean>
解決
私があなたが正しいことを理解している場合、あなたはMyServiceを拡張し、注釈が付けられ、好ましい引数とともにすべてのクラスのすべての方法を見つけるポイントカットが必要です。
私はあなたが交換することを提案します:
execution(public * com.mycompany.myserviceimpl.*(..))
と:
execution(public * com.mycompany.myservice.MyService+.*(..))
JoinPointがMyServiceクラスまたはそれを拡張するクラスと一致させる場合は、プラスサインが使用されます。
私はそれが役立つことを願っています!
他のヒント
ESPEN、あなたのコードは1つのクラスでのみ機能します:
execution(public * com.mycompany.myservice.MyService+.*(..))
しかし、*com.mycompany.services。**パッケージのすべてのサービスに対してこの動作が必要な場合はどうなりますか?