【springboot】AOP(注解版)使用例子


1、簡單使用,打印訪問方法時,進入、方法全限定名稱、參數索引位置、參數類型及內容(如果為null就只打印null)、正常/異常退出。

1.1、定義注解用於切面

package com.frame.annotation;


import java.lang.annotation.*;

/**
 * 方法日志注解
 *
 * @author lw
 * @version V1.0
 * @Title: MothodLog.java
 * @Package com.frame.base.annotation
 * @Description: 注解在被訪問的方法時,打印類名、方法名、參數。方便上線排錯
 * @date 2019年12月23日 下午3:21:33
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MothodLogPrint {
}

 

1.2、切面類

package com.frame.sys.aop;

import com.frame.annotation.MothodLogPrint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.Collection;
import java.util.Map;

/**
 * MothodLogPrintAspect利用spring的aop實現日志的打印
 *
 * @auther lw
 * @date 2019-12-24 15:32:33
 */
@Aspect
@Component
public class MothodLogPrintAspect {

    private static final Logger logger = LoggerFactory.getLogger(MothodLogPrintAspect.class);

    @Around("@annotation(mothodLogPrint)")
    public Object advice(ProceedingJoinPoint joinPoint, MothodLogPrint mothodLogPrint){
        String className = joinPoint.getTarget().getClass().getName();
        String mothodName = joinPoint.getSignature().getName();
        logger.info(">>>>>>>>>進入,方法:[" + className + "." + mothodName + "]");
        Object[] args = joinPoint.getArgs();
        String mothodPropertion = getMothodPropertion(className, mothodName, args);
        logger.info(mothodPropertion);
        Object proceed = null;
        try {
            proceed = joinPoint.proceed();
            logger.info("<<<<<<<<<正常,退出方法:[" + className + "." + mothodName + "]");
        } catch (Throwable throwable) {
            logger.error(throwable.getMessage(), throwable);
            logger.info("<<<<<<<<<異常,退出方法:[" + className + "." + mothodName + "]");
        }
        return proceed;
    }

    /**
     * 獲取方法和參數內容
     *
     * @param className 類名 非必填
     * @param mothodName 方法名 必填
     * @param agrs 參數列表
     * @return
     */
    public static String getMothodPropertion(String className, String mothodName, Object ... agrs) {
        StringBuilder sb = new StringBuilder();
        if(null != className) {
            sb.append("類名:[").append(className).append("]\r\n");
        }
        sb.append("方法:[").append(mothodName).append("]");
        if(null != agrs) {
            for(int i = 0; i < agrs.length; i++) {
                Object obj = agrs[i];
                sb.append("\r\n參數索引:[").append(i).append("],");
                if(null == obj) {
                    sb.append("為null");
                } else {
                    sb.append("類型:[").append(obj.getClass().getName()).append("],");
                    if(obj instanceof Collection) {
                        Collection collection = (Collection)obj;
                        sb.append("長度:[").append(collection.size()).append("],內容:[").append(collection).append("]");
                    } else if(obj instanceof Map) {
                        Map map = (Map)obj;
                        sb.append("長度:[").append(map.size()).append("],內容:[").append(map).append("]");
                    } else if(obj.getClass().isArray()) {
                        Object[] objects = (Object[])obj;
                        sb.append("長度:[").append(objects.length).append("],內容:[").append(objects).append("]");
                    } else if(obj instanceof String) {
                        sb.append("內容:[").append(obj).append("]");
                    } else {
                        sb.append("內容:[").append(String.valueOf(obj)).append("]");
                    }
                }
            }
        }
        return sb.toString();
    }

}

 

1.3、用於切面的例子

com.frame.solr.service.SolrService#getByMap

 

1.4、打印日記

 

 

2、切面修改參數再訪問

2.1、注解

package com.frame.annotation;


import java.lang.annotation.*;

/**
 * solr、db查詢模式
 *
 * @author lw
 * @version V1.0
 * @Title: SolrOrDbStrategy.java
 * @Package com.frame.base.annotation
 * @Description: 注解在被訪問的方法時,方式有個參數可根據solr還是db來進行查詢
 * @date 2020年2月11日 下午4:21:33
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SolrOrDbStrategy {
}

 

2.2、切面類

package com.frame.sys.aop;

import com.frame.annotation.SolrOrDbStrategy;
import com.frame.modules.dabis.archives.ArchivesConstant;
import com.frame.solr.em.SolrCode;
import com.frame.solr.service.SolrService;
import com.frame.strategy.StrategySituation;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * SolrOrDbStrategyAspect利用spring的aop實現solr查詢異常時轉db
 * 默認是用solr查詢,如果solr斷了就切換到mysql查詢。如果是solr語句有問題則不切換
 *
 * @auther lw
 * @date 2020-2-11 16:20:33
 */
@Aspect
@Component
public class SolrOrDbStrategyAspect {

    private static final Logger logger = LoggerFactory.getLogger(SolrOrDbStrategyAspect.class);

    @Autowired
    private SolrService solrService;

    @Autowired
    private StrategySituation strategySituation;

    @Around("@annotation(solrOrDbStrategy)")
    public Object advice(ProceedingJoinPoint joinPoint, SolrOrDbStrategy solrOrDbStrategy){
        Object[] args = joinPoint.getArgs();
        Object proceed = null;
        try {
            if (ArchivesConstant.queryType.SOLR.getValue().equals(StrategySituation.getTheCurrentStrategy())) {
                proceed = joinPoint.proceed();
                logger.info("使用solr查詢");
            } else {
                for (int i = 0; i < args.length; i++) {
                    Object obj = args[i];
                    if (ArchivesConstant.queryType.SOLR.getValue().equals(obj) || ArchivesConstant.queryType.DB.getValue().equals(obj)) {
                        // 修改參數
                        args[i] = ArchivesConstant.queryType.DB.getValue();
                        break;
                    }
                }
                // 修改參數后再執行方法
                proceed = joinPoint.proceed(args);
                logger.info("使用db查詢");
            }
        } catch (Throwable throwable) {
            if (solrService.detectSolrConnection(SolrCode.ARCHIVES.getValue())) {
                logger.error("solr連接正常,solr語句有誤", throwable);
            } else {
                for (int i = 0; i < args.length; i++) {
                    Object obj = args[i];
                    if (ArchivesConstant.queryType.SOLR.getValue().equals(obj) || ArchivesConstant.queryType.DB.getValue().equals(obj)) {
                        // 修改參數
                        args[i] = ArchivesConstant.queryType.DB.getValue();
                        break;
                    }
                }
                try {
                    // 修改參數后再執行方法
                    proceed = joinPoint.proceed(args);
                    logger.error("solr連接異常,轉db查詢");
                    strategySituation.switchState(ArchivesConstant.queryType.DB.getValue());
                } catch (Throwable e) {
                    logger.error("db查詢異常", e);
                }
            }
        }
        return proceed;
    }

}

 

 

2.3、切入

 

 

2.4、結果

正常

 

solr斷了

 

 

 

3、可根據類型處理

3.1、注解需要type

 

 3.2、切面類根據不同type處理

 

3.3、切入

 

 

 


免責聲明!

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



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