我有一个在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());
}
}
参数对象包含用户名,我想在允许访问该方法之前查找用户所需的角色。
当我在MeServiceImpl中的方法上放置注释时,一切正常,切入点匹配并且方面启动。但是,我认为注释是服务契约的一部分,应该与接口一起发布单独的API包。显然,我不想将注释放在服务定义和实现(DRY)上。
我知道在Spring AOP中有一些情况,其中方面是由一个接口方法(例如Transactional)的注释触发的。这里是否有特殊的语法,或者它是开箱即用的。
PS:我没有发布我的弹簧配置,因为它似乎工作得很好。不,这些既不是我原来的类也不是方法名。
PPS:实际上,这是我的春季配置的相关部分:
<aop:aspectj-autoproxy proxy-target-class="false" />
<bean class="com.mycompany.aspect.MyAspect">
<property name="userService" ref="userService" />
</bean>
答案 0 :(得分:31)
如果我理解你是正确的,你需要一个切入点来查找扩展MyService的类中的所有方法,并使用首选参数进行注释。
我建议你替换:
execution(public * com.mycompany.myserviceimpl.*(..))
使用:
execution(public * com.mycompany.myservice.MyService+.*(..))
如果您希望连接点与MyService类或扩展它的类匹配,则使用加号。
我希望它有所帮助!
答案 1 :(得分:4)
Espen,您的代码仅适用于一个类:
execution(public * com.mycompany.myservice.MyService+.*(..))
但如果我想在* com.mycompany.services。**包中的所有服务中使用此行为怎么办?
答案 2 :(得分:1)
答案 3 :(得分:0)
我遇到了同样的问题,但上面的建议没有帮助。 如果我只将其作为切入点:
execution(public * com.mycompany.myservice.MyService+.*(..))
然后调用建议。但是,如果我添加这个:
&& @annotation(x.y.z.Logged)
然后不会调用建议。 MyService接口在其某个方法上包含@Logged注释,甚至包含其类型声明。
答案 4 :(得分:0)
您应该将@Inherited注释添加到@RequiredPermission注释中。
http://download.oracle.com/javase/6/docs/api/java/lang/annotation/Inherited.html