springboot Aop配置,並使用自定義注解annotation,並且攔截service層


前言

用Spring Boot的AOP來簡化處理自定義注解,並將通過實現一個簡單的方法執行判斷節點是否開始的狀態示列源碼。

AOP概念

面向側面的程序設計(aspect-oriented programming,AOP,又譯作面向方面的程序設計、觀點導向編程、剖面導向程序設計)是計算機科學中的一個術語,指一種程序設計范型。該范型以一種稱為側面(aspect,又譯作方面)的語言構造為基礎,側面是一種新的模塊化機制,用來描述分散在對象、類或函數中的橫切關注點(crosscutting concern)。

Spring Boot的AOP環境准備

pom.xml中引入相應的依賴模塊

<!-- AOP依賴模塊 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency> 

先建一個簡單地建一個自定義注解類

一個簡單地自定義注解類就生成了:

package com.common.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 自定義注解
 * @Description 自定義注解@HAStatusCheck  攔截service層   HAStatusCheckService
 * @Author Justin zeng 
 * @Date 2019-04-19
 * @version 1.0
 */
@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface HAStatusCheck {
    //自定義的方法描述信息 
    String description()  default "";
}

在建一個切點類實現你的要處理的事情

package com.common.aop;

import java.lang.reflect.Executable;
import java.lang.reflect.Method;
import java.util.ArrayList;

import javax.annotation.Resource;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.aspectj.lang.reflect.MethodSignature;

import com.common.annotation.HAStatusCheck;
import com.common.enums.ha.ServerPort;
import com.common.enums.ha.ServerType;
import com.common.ha.HAStatusCheckService;
/**
 * 切點類
 * @Description AOP攔截判斷 HA節點是否開啟狀態方法Service層
 * @Author Justin zeng 
 * @Date 2019-04-19
 * @version 1.0
 */
@Aspect
@Component
public class HAStatusCheckAop {
    //注入Service
    @Resource
    private HAStatusCheckService hAStatusCheckService;
    private static final Logger LOG = LoggerFactory.getLogger(HAStatusCheckAop.class);
    
    //Service層切點  自定義的注解類路徑
    @Pointcut("@annotation(com.common.annotation.HAStatusCheck)")
     public void servicePointCut() {}
    
    Object proceed=null;
    @Around("servicePointCut()")
    public void logAroundService(ProceedingJoinPoint jointPoint) throws Throwable {
        LOG.info("------判斷節點開始------");
        ArrayList<String> list = new ArrayList<String>();
        list.add("192.168.1.5");
        if (!hAStatusCheckService.isActAsActiveNode(list, ServerPort.BILLING_HANDLER,  ServerType.BILLING_HANDLER)) {
            LOG.info("------訪問請求不合法!------");
            return;
            //強制退出
            //System.exit(0);
        }else {
            LOG.info("------判斷注解開始------");
            //獲得當前訪問的class  
            Class<?> className = jointPoint.getTarget().getClass(); 
            //獲得訪問的方法名  
            String methodName = jointPoint.getSignature().getName();  
            //得到方法的參數的類型  
            Class[] argClass = ((MethodSignature) jointPoint.getSignature()).getParameterTypes();  
            try {
                 // 得到訪問的方法對象  
                Method method = className.getDeclaredMethod(methodName, argClass);
                // 判斷是否存在@HAStatusCheck注解  
                if (method.isAnnotationPresent(HAStatusCheck.class)) {  
                    HAStatusCheck annotation = method.getAnnotation(HAStatusCheck.class);  
                    annotation.description();
                    LOG.info("當前目標執行方法:"+methodName+"執行開始");
                    //執行當前目標中的方法
                    proceed = jointPoint.proceed();  
                    LOG.info("當前目標class路徑:"+className);
                    LOG.info("當前目標執行方法名:" + methodName);
                    LOG.info("當前目標執行方法的參數類型:" + argClass);
                    LOG.info("當前目標方法執行的結果:" + proceed);
                    LOG.info("當前目標執行方法:"+methodName+"執行結束");
                }  
            } catch (Exception e) {  
                LOG.error("不存在@HAStatusCheck注解",e);
            }     
        }
    }

    /**
     * 獲取注解中對方法的描述信息 用於service層注解
     *
     * @param joinPoint 切點
     * @return 方法描述
     * @throws Exception
     */
     public  static String getServiceMthodDescription(JoinPoint joinPoint)
             throws Exception {
        String targetName = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();
        Object[] arguments = joinPoint.getArgs();
        Class targetClass = Class.forName(targetName);
        Method[] methods = targetClass.getMethods();
        String description = "";
         for (Method method : methods) {
             if (method.getName().equals(methodName)) {
                Class[] clazzs = method.getParameterTypes();
                 if (clazzs.length == arguments.length) {
                    description = method.getAnnotation(HAStatusCheck. class).description();
                    LOG.info("======"+description+"======");
                    break;
                }
            }
        }
         return description;
    }

}

最后

在你需要的判斷預處理的地方加上自定義的注解 @HAStatusCheck 

package com.job;

import com.annotation.HAStatusCheck;

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class TestJob {
        //這就是上面自定義的注解
    @HAStatusCheck
    public void job() throws Exception {
        System.out.println("TestJob job run ....");
    }
}

這樣自定義注解攔截service層開發就結束了,需要的可以試試吧,希望能幫到大家。 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM