Java Annotation+AspectJ是绝配啊

最近开始学着做Java服务器端开发,对注解一知半解的。今天刚好发现有一个业务场景可以通过自己实现注解简化代码,所以尝试着做起来。我发现Annotation+AspectJ是一个非常强大的组合,可以做很多事情。

下面这个checkRamPermission方法是用来做权限检查的。基本上各个入口方法都需要在最开始的地方加上这行代码。看起来很繁琐,也不够酷。所以琢磨用注解的方法来实现。

openApiUtil.checkRamPermission(request, request.getAction(), ResouceType.PRODUCT, String.valueOf(request.getProductId()), true);

checkRamPermission方法的参数分为好几种。分别如下所示。

  1. 请求者传入的参数,如request。
  2. 不同语境下的固定参数。如ResouceType.PRODUCT。
  3. 不同语境下从request各子类里面提取的属性。如request.getProductId()。

针对上面这些参数定义好注解。请求者传入的参数可以通过反射获取。注解里面只需包含语境相关的信息就行。

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface RAMAnnotation {

    public String resourceType();
    public String resourceId() default "";
}

接着定义好AspectJ的pointcut。

@Aspect
public class RAMPointCut {

    @Pointcut("@annotation(com.alibaba.cloudmobile.mhub.util.RAMAnnotation)")
    public void checkPemission() {}
}

接着就是实现拦截的方法。通过joinPoint获取到方法的信息,包括参数值,这样就可以获取到request对象。因为request子类众多,需要resourceId辅助,以获取具体子类方法,进一步得到resourceId。

@Before(value = "com.alibaba.cloudmobile.mhub.util.RAMPointCut.checkPemission()")
public void ramCheckPemission(JoinPoint joinPoint) {

    try {

        MethodSignature methodSig = (MethodSignature) joinPoint.getSignature();
        Annotation[] annotations = methodSig.getMethod().getDeclaredAnnotations();
        RAMAnnotation annotation = (RAMAnnotation) annotations[0];

        Object[] methodArgs = joinPoint.getArgs();

        BasePopRequest request = (BasePopRequest) methodArgs[0];
        String action = request.getAction();

        String resourceId = null;
        Method method = null;

        if (annotation.resourceId().equals("productId")) {

            method = request.getClass().getDeclaredMethod("getProductId");
        } else if (annotation.resourceId().equals("appId")) {

            method = request.getClass().getDeclaredMethod("getAppId");
        }

        if (method != null) {
            resourceId = String.valueOf(method.invoke(request));
        }

        openApiUtil.checkRamPermission(request, action, annotation.resourceType(), resourceId, true);

    } catch (Throwable e) {

        logger.error("RAMAnnotation" + e.getMessage());
        throw e;
    }
}

使用方式如下。resourceType和resourceId使用枚举类型会很合理一些。注解的属性只支持Java的内置类型,不支持用户自定义的类型。

@RAMAnnotation(resourceType = "product", resourceId = "productId")
public QueryProductInfoResponse queryProductInfo(QueryProductInfoRequest request) throws Throwable
{
}

参考资料。

  1. 十分钟全面理解Spring AOP
  2. 基于 Annotation 拦截的 Spring AOP 权限验证方法
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 从三月份找实习到现在,面了一些公司,挂了不少,但最终还是拿到小米、百度、阿里、京东、新浪、CVTE、乐视家的研发岗...
    时芥蓝阅读 42,486评论 11 349
  • 这部分主要是开源Java EE框架方面的内容,包括Hibernate、MyBatis、Spring、Spring ...
    杂货铺老板阅读 5,303评论 0 2
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 135,828评论 19 139
  • 本文章涉及代码已放到github上annotation-study 1.Annotation为何而来 What:A...
    zlcook阅读 29,456评论 15 116
  • 时间过得真快 真快啊 那时候上学放学都是一个人走背着好重好重的书包,走最偏僻人最少的路回家,最害怕碰见同学或者是邻...
    VXUN阅读 1,625评论 2 0

友情链接更多精彩内容