Java Annotation+AspectJ是絕配啊

最近開始學(xué)著做Java服務(wù)器端開發(fā),對(duì)注解一知半解的。今天剛好發(fā)現(xiàn)有一個(gè)業(yè)務(wù)場(chǎng)景可以通過自己實(shí)現(xiàn)注解簡化代碼,所以嘗試著做起來。我發(fā)現(xiàn)Annotation+AspectJ是一個(gè)非常強(qiáng)大的組合,可以做很多事情。

下面這個(gè)checkRamPermission方法是用來做權(quán)限檢查的?;旧细鱾€(gè)入口方法都需要在最開始的地方加上這行代碼??雌饋砗芊爆?,也不夠酷。所以琢磨用注解的方法來實(shí)現(xiàn)。

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

checkRamPermission方法的參數(shù)分為好幾種。分別如下所示。

  1. 請(qǐng)求者傳入的參數(shù),如request。
  2. 不同語境下的固定參數(shù)。如ResouceType.PRODUCT。
  3. 不同語境下從request各子類里面提取的屬性。如request.getProductId()。

針對(duì)上面這些參數(shù)定義好注解。請(qǐng)求者傳入的參數(shù)可以通過反射獲取。注解里面只需包含語境相關(guān)的信息就行。

@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() {}
}

接著就是實(shí)現(xiàn)攔截的方法。通過joinPoint獲取到方法的信息,包括參數(shù)值,這樣就可以獲取到request對(duì)象。因?yàn)閞equest子類眾多,需要resourceId輔助,以獲取具體子類方法,進(jìn)一步得到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使用枚舉類型會(huì)很合理一些。注解的屬性只支持Java的內(nèi)置類型,不支持用戶自定義的類型。

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

參考資料。

  1. 十分鐘全面理解Spring AOP
  2. 基于 Annotation 攔截的 Spring AOP 權(quán)限驗(yàn)證方法
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 從三月份找實(shí)習(xí)到現(xiàn)在,面了一些公司,掛了不少,但最終還是拿到小米、百度、阿里、京東、新浪、CVTE、樂視家的研發(fā)崗...
    時(shí)芥藍(lán)閱讀 42,790評(píng)論 11 349
  • 這部分主要是開源Java EE框架方面的內(nèi)容,包括Hibernate、MyBatis、Spring、Spring ...
    雜貨鋪老板閱讀 1,556評(píng)論 0 2
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,545評(píng)論 19 139
  • 本文章涉及代碼已放到github上annotation-study 1.Annotation為何而來 What:A...
    zlcook閱讀 29,747評(píng)論 15 116
  • 時(shí)間過得真快 真快啊 那時(shí)候上學(xué)放學(xué)都是一個(gè)人走背著好重好重的書包,走最偏僻人最少的路回家,最害怕碰見同學(xué)或者是鄰...
    VXUN閱讀 247評(píng)論 2 0

友情鏈接更多精彩內(nèi)容