springboot實(shí)現(xiàn)基于aop的切面日志
本文實(shí)例為大家分享了springboot實(shí)現(xiàn)基于aop的切面日志的具體代碼,供大家參考,具體內(nèi)容如下
通過aop的切面方式實(shí)現(xiàn)日志
通切面攔截所有指定包下的所有方法
@Aspect @Component @EnableAspectJAutoProxy public class LogAspect1{ ? ? Logger logger = LoggerFactory.getLogger(LogAspect.class); ? ?? /** ?* 攔截切點(diǎn) ?*/ ? ? @Pointcut("execution(*xx.xx.controller.*.*(..))") ? ? private void logPointCut() { ? ? ? ? logger.info("進(jìn)入注解攔截"); ? ? } ? ? //前置通知,在方法之前通知 ? ? @Before(value = "logPointCut()") ? ? public void before(JoinPoint jp) { ? ? ? ? logger.info("方法調(diào)用前:" + "類名:" + jp.getTarget().getClass().getName() + "方法名 :" + jp.getSignature().getName()); ? ? } ? ? //后置通知 ? ? @After(value = "logPointCut()") ? ? public void doAfter(JoinPoint jp) { ? ? ? ? logger.info("方法調(diào)用結(jié)束:" + "類名:" + jp.getTarget().getClass().getName() + "方法名 :" + jp.getSignature().getName()); ? ? } ? ? //環(huán)繞通知 ? ? @Around("logPointCut()") ? ? public Object doAround(ProceedingJoinPoint pjp) throws Throwable { ? ? ? ? logger.info("方法開始調(diào)用》》》》》》"); ? ? ? ? Object retVal = pjp.proceed(); ? ? ? ? logger.info("方法調(diào)用結(jié)束》》》》》》"); ? ? ? ? return retVal; ? ? } ? ? //返回通知 ? ? @AfterReturning(pointcut = "logPointCut()") ? ? public void doAfterReturning(JoinPoint jp) { ? ? ? ? logger.info("寫入日志"); ? ? } ? ? //異常通知 ? ? @AfterThrowing(pointcut = "logPointCut()", throwing = "ex") ? ? public void doAfterThrowing(JoinPoint jp, Throwable ex) { ? ? ? ? logger.info("方法異常,異常信息:" + ex.getMessage()); ? ? } }
攔截自定義注解
定義一個(gè)日志注解,在所有要需要記錄的方法上加蓋注解即可被后續(xù)的aop攔截處理
代碼如下
@Target({ElementType.PARAMETER, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Log { ? ? /** ? ? ?* 日志主題 ? ? ?*/ ? ? public String title() default ""; ? ? /** ? ? ?* 操作具體業(yè)務(wù) ? ? ?*/ ? ? public String business() default ""; ? ? /** ? ? ?* 是否保留請求參數(shù) ? ? ?*/ ? ? public boolean isSaveRequestData() default false; ? ? /** ? ? * 日志的類別,主要用于日志的分開記錄和查詢 ? ? **/ LogType logType() default LogType.LOGIN; }
攔截切面的實(shí)現(xiàn)
@Aspect @Component @EnableAspectJAutoProxy public class LogAspect { ? ? Logger logger = LoggerFactory.getLogger(LogAspect.class); ? ? @Autowired ? ? private ServiceDemo serviceDemo; ? ? /** ? ? ?* 攔截切點(diǎn) ? ? ?*/ ? ? @Pointcut("@annotation(moling.evolution.demo.aop.annotation.Log)") ? ? private void logPointCut() { ? ? ?? ? ? } ? ? //前置通知,在方法之前通知 ? ? @Before(value = "logPointCut()") ? ? public void before(JoinPoint jp) { ? ? ? ? logger.info("方法調(diào)用前:" + "類名:" + jp.getTarget().getClass().getName() + "方法名 :" + jp.getSignature().getName()); ? ? } ? ? //后置通知 ? ? @After(value = "logPointCut()") ? ? public void doAfter(JoinPoint jp) { ? ? ? ? logger.info("方法參數(shù):{}", jp.getArgs()); ? ? ? ? logger.info(" ?{} || {}", jp.getStaticPart().getId(), jp.getStaticPart().getSourceLocation()); ? ? ? ? jp.getStaticPart().getId(); ? ? ? ? logger.info("方法調(diào)用結(jié)束:" + "類名:" + jp.getTarget().getClass().getName() + "方法名 :" + jp.getSignature().getName()); ? ? } ? ? //環(huán)繞通知 ? ? @Around("logPointCut()") ? ? public Object doAround(ProceedingJoinPoint pjp) throws Throwable { ? ? ? ? logger.info("方法開始調(diào)用》》》》》》"); ? ? ? ? Object retVal = pjp.proceed(); ? ? ? ? logger.info("方法調(diào)用結(jié)束》》》》》》"); ? ? ? ? return retVal; ? ? } ? ? //返回通知 ? ? @AfterReturning(pointcut = "logPointCut()", returning = "object") ? ? public void doAfterReturning(JoinPoint jp, Object object) { ? ? ? ? System.out.println("返回通知"); ? ? ? ? Log log = null; ? ? ? ? try { ? ? ? ? ? ? log = getAnnotationLog(jp); ? ? ? ? } catch (Exception e) { ? ? ? ? ? ? e.printStackTrace(); ? ? ? ? } ? ? ? ? System.out.println(object); ? ? ? ? System.out.println(log); ? ? ? ? if (log != null) { ? ? ? ? ? ? logger.info(log.title()); ? ? ? ? ? ? logger.info(log.business()); ? ? ? ? ? ? logger.info(log.user()); ? ? ? ? ? ? logger.info(log.isSaveRequestData() + ""); ? ? ? ? } else { ? ? ? ? ? ? logger.error("獲取注解信息失敗"); ? ? ? ? } ? ? ? ? serviceDemo.demo(); ? ? } ? ? //異常通知 ? ? @AfterThrowing(pointcut = "logPointCut()", throwing = "ex") ? ? public void doAfterThrowing(JoinPoint jp, Throwable ex) { ? ? ? ? logger.info("方法異常,異常信息:" + ex.getMessage()); ? ? ? ? serviceDemo.error(); ? ? } ? ? /** ? ? ?* 是否存在注解,如果存在就獲取 ? ? ?*/ ? ? private Log getAnnotationLog(JoinPoint joinPoint) throws Exception { ? ? ? ? Signature signature = joinPoint.getSignature(); ? ? ? ? MethodSignature methodSignature = (MethodSignature) signature; ? ? ? ? Method method = methodSignature.getMethod(); ? ? ? ? if (method != null) { ? ? ? ? ? ? return method.getAnnotation(Log.class); ? ? ? ? } ? ? ? ? return null; ? ? } }
基于事件通知實(shí)現(xiàn)日志的記錄
- 攔截切面的實(shí)現(xiàn)
@Aspect @Component @EnableAspectJAutoProxy public class LogAspectContext { ? ? Logger logger = LoggerFactory.getLogger(LogAspectContext.class); ? ? @Autowired ? ? private ApplicationContext applicationContext; ? ? /** ? ? ?* 攔截切點(diǎn) ? ? ?*/ ? ? @Pointcut("@annotation(moling.evolution.demo.aop.annotation.Log)") ? ? private void logPointCut() { ? ? ? ? logger.info("進(jìn)入注解攔截"); ? ? } ? ? //返回通知 ? ? @AfterReturning(pointcut = "logPointCut()", returning = "object") ? ? public void doAfterReturning(JoinPoint jp, Object object) throws Exception { ? ? ? ? applicationContext.publishEvent(new LogSuccessEvent(jp, null)); ? ? } ? ? //異常通知 ? ? @AfterThrowing(pointcut = "logPointCut()", throwing = "ex") ? ? public void doAfterThrowing(JoinPoint jp, Throwable ex) { ? ? ? ? logger.info("方法異常,異常信息:" + ex.getMessage()); ? ? ? ? applicationContext.publishEvent(new LogSuccessEvent(jp, ex)); ? ? } ? ? /** ? ? ?* 是否存在注解,如果存在就獲取 ? ? ?*/ ? ? private Log getAnnotationLog(JoinPoint joinPoint) throws Exception { ? ? ? ? Signature signature = joinPoint.getSignature(); ? ? ? ? MethodSignature methodSignature = (MethodSignature) signature; ? ? ? ? Method method = methodSignature.getMethod(); ? ? ? ? if (method != null) { ? ? ? ? ? ? return method.getAnnotation(Log.class); ? ? ? ? } ? ? ? ? return null; ? ? } }
@Slf4j @Service public class ApplicationListener implements org.springframework.context.ApplicationListener<LogSuccessEvent> { ? ? @Autowired ? ? private ServiceDemo demo; ? ? @Override ? ? public void onApplicationEvent(LogSuccessEvent event) { ? ? ? ? JoinPoint joinPoint = event.getJp(); ? ? ? ? Throwable ex = event.getThrowable(); ? ? ? ? if (ex == null) { ? ? ? ? ? ? demo.demo(); ? ? ? ? } else { ? ? ? ? ? ? demo.error(); ? ? ? ? } ? ? } }
@Slf4j public class LogSuccessEvent extends ApplicationEvent { ? ? /** ? ? ?* Create a new ApplicationEvent. ? ? ?* ? ? ?* @param source the component that published the event (never {@code null}) ? ? ?*/ ? ? private JoinPoint jp; ? ? private Throwable throwable; ? ? public LogSuccessEvent(Object source, Throwable throwable) { ? ? ? ? super(source); ? ? ? ? this.throwable = throwable; ? ? ? ? this.jp = (JoinPoint) source; // ? ? ? ?Log logger = (Log) source; // ? ? ? ?log.info(logger.title()); // ? ? ? ?log.info(logger.business()); // ? ? ? ?log.info(logger.user()); // ? ? ? log.info(logger.isSaveRequestData() + ""); ? ? } ? ? public JoinPoint getJp() { ? ? ? ? return jp; ? ? } ? ? public Throwable getThrowable() { ? ? ? ? return throwable; ? ? } }
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
關(guān)于MyBatis中SqlSessionFactory和SqlSession簡解
這篇文章主要介紹了MyBatis中SqlSessionFactory和SqlSession簡解,具有很好的參考價(jià)值,希望大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12SpringBoot?mybatis-plus使用json字段實(shí)戰(zhàn)指南
在現(xiàn)代應(yīng)用開發(fā)中經(jīng)常會(huì)使用JSON格式存儲(chǔ)和傳輸數(shù)據(jù),為了便捷地處理數(shù)據(jù)庫中的JSON字段,MyBatis-Plus提供了強(qiáng)大的JSON處理器,這篇文章主要給大家介紹了關(guān)于SpringBoot?mybatis-plus使用json字段的相關(guān)資料,需要的朋友可以參考下2024-01-01Java多線程之循環(huán)柵欄技術(shù)CyclicBarrier使用探索
這篇文章主要介紹了Java多線程之循環(huán)柵欄技術(shù)CyclicBarrier,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪<BR>2024-01-01JDK20?+?SpringBoot?3.1.0?+?JdbcTemplate?使用案例詳解
通過 JdbcTemplate 直接執(zhí)行 SQL 語句,結(jié)合源碼動(dòng)態(tài)編譯即可方便實(shí)現(xiàn)動(dòng)態(tài)修改代碼邏輯的效果,這篇文章主要介紹了JDK20?+?SpringBoot?3.1.0?+?JdbcTemplate?使用,需要的朋友可以參考下2023-09-09簡單談?wù)刯ava中匿名內(nèi)部類構(gòu)造函數(shù)
這篇文章主要簡單給我們介紹了java中匿名內(nèi)部類構(gòu)造函數(shù),并附上了簡單的示例,有需要的小伙伴可以參考下。2015-11-11教你一步到位部署運(yùn)行MyBatis3源碼(保姆級)
一個(gè)框架的運(yùn)行流程從最簡單的一個(gè)helloworld來看其源碼就能了解到框架的原理是什么,這篇文章主要給大家介紹了關(guān)于如何一步到位部署運(yùn)行MyBatis3源碼的相關(guān)資料,需要的朋友可以參考下2022-06-06Java實(shí)現(xiàn)的計(jì)算稀疏矩陣余弦相似度示例
這篇文章主要介紹了Java實(shí)現(xiàn)的計(jì)算稀疏矩陣余弦相似度功能,涉及java基于HashMap的數(shù)值計(jì)算相關(guān)操作技巧,需要的朋友可以參考下2018-07-07