在我的 之前的简短抱怨 中,我向您展示了如何使用@Alternative以及替代元数据来轻松更改基于部署场景的Bean实现。但这并不是故事的结束。在部署时,我有时还希望更改两样东西
- 拦截器
- 装饰器
让我们考虑安全问题。假设我有一个拦截器,该拦截器为“业务层”中的Beans实现了方法级别的基于角色的安全。
@Secure @Interceptor
class SecurityInterceptor {
@Inject User user;
@AroundInvoke
Object checkRole(InvocationContext ctx) throws Exception {
String[] roles = ctx.getMethod().getAnnotation(Secure.class).value();
for (String role: role) {
if ( !user.getRoles().contains(role) ) throw new AuthorizationException(role);
}
return ctx.proceed();
}
}
我还有一个独立的数据访问层,由以下接口实现的Beans组成
public interface DataAccess<T, V> {
public V getId(T object);
public T load(V id);
public void save(T object);
public void delete(T object);
public Class<T> getDataType();
...
}
并且我有一个装饰器,它为我的数据访问层添加了行级安全。
@Decorator
class DataSecurityDecorator<T, V> implements DataAccess<T, V> {
@Inject @Delegate DataAccess<T, V> delegate;
@Inject User user;
public void save(T object) {
authorize(SecureAction.SAVE, object);
delegate.save(object);
}
public void delete(T object) {
authorize(SecureAction.DELETE, object);
delegate.delete(object);
}
private void authorize(SecureAction action, T object) {
V id = delegate.getId(object);
Class<T> type = delegate.getDataType();
if ( !user.getPermissions().contains( new Permission(action, type, id) ) ) {
throw new AuthorizationException(action);
}
}
}
这一切都很不错,但在我的测试环境中,我不想启用这些拦截器和装饰器。这就是为什么默认情况下,它们没有被启用。
我们需要显式地启用拦截器和装饰器,以便为所有需要安全访问控制的部署声明它们beans.xml.
<beans>
<interceptors>
<class>org.mycompany.security.SecurityInterceptor</class>
</interceptors>
<decorators>
<class>org.mycompany.security.DataSecurityDecorator</class>
</decorators>
</beans>