【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("]
");
        }
        sb.append("方法:[").append(mothodName).append("]");
        if(null != agrs) {
            for(int i = 0; i < agrs.length; i++) {
                Object obj = agrs[i];
                sb.append("
参数索引:[").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、切入

 

原文地址:https://www.cnblogs.com/xiaostudy/p/12336147.html