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、切入