springbootAOP(注解版)使用例子
Posted xiaostudy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了springbootAOP(注解版)使用例子相关的知识,希望对你有一定的参考价值。
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、切入
以上是关于springbootAOP(注解版)使用例子的主要内容,如果未能解决你的问题,请参考以下文章
SpringBoot AOP学习:Spring AOP实现日志功能
IOC 控制反转Android 事件依赖注入 ( 事件依赖注入具体的操作细节 | 创建 事件监听器 对应的 动态代理 | 动态代理的数据准备 | 创建调用处理程序 | 创建动态代理实例对象 )(代码片