java 自定义注解+AOP实现日志记录
ssm版本:
1、首先自定義一個注解,該注解有兩個屬性,一個是模塊名,一個是操作的內容。該注解是用來修飾Service層中的方法的。
2、創建一個切面類,該切面使用@Aspect和@Component注解修飾,該頁面需要注入一個HttpSession對象。
注意:一個普通的java類是不能注入HttpSession對象的,因此需要在web.xml文件中配置
org.springframework.web.util.IntrospectorCleanupListenerorg.springframework.web.context.request.RequestContextListener3、在applicationContext.xml文件中配置aop:aspectj-autoproxy,掃描@Aspect注解。
springboot版本:
日志管理:
1、首先自定義一個注解,自定義的注解需要使用@Target(ElementType.METHOD),@Retention(RetentionPolicy.RUNTIME)修飾,然后給幾個屬性。
2、定義一個切面然后切面使用@Component,@Aspect修飾,然后定義掃描切入點表達式@After(“execution(* com.syzw.test…service…*(…))”),創建通知類型,通知類型里面可以使用 HttpServletRequest request=((ServletRequestAttributes)(RequestContextHolder.getRequestAttributes())).getRequest();去獲取requet對象。
3、在該方法中就可以通過JoinPoint形參去獲取實際操作對象的class類,然后就可以獲取該到方法,然后可以獲取到自定義的注解了就完成了日志的管理。
缺點:
如果需要進行比較信息的日志管理的話,需要在每一個操作dao接口的方法上添加自定義的注解,較為麻煩。
解決方式:
一般會在切面上判斷url然后根據url去做相應的操作的,但是這種操作較不靈活。
JoinPoint是一個切入點,它封裝了切入點和真實對象的一些信息。
JoinPoint常用的一些api:
getSignature():獲取真實訪問方法的全路徑簽名。
getArgs():獲取傳入目標方法的參數對象。
getTarget():獲取被代理的對象。
getThis():獲取代理對象。
Signature:
getName():獲取操作的方法名。
getClass():獲取方法所在的Class類。
注意:
其實每一個注解都對應了一個切面,注解只是其一個聲明作用,并沒有實際的意義。
使用Spring Aop自定義注解實現自動記錄日志
(1)首先配置文件:
<!-- 聲明自動為spring容器中配置@aspectj切面的bean建立代理 ,織入切面 --><aop:aspectj-autoproxy /><!-- 開啟注解掃描 --><context:component-scan base-package="com.ky.zhjd.**"/><!-- 為true說明代理基于類被建立(默認false,基于接口被建立) --><aop:config proxy-target-class="true"></aop:config>(2)建立一個自定義注解類spring
注意建立時選Annotation,類名我叫ArchivesLog(日志檔案的意思)。
ArchivesLog.java內容:
package com.ky.zhjd.common.log;import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /*** * 自定義注解類**/ @Target({ElementType.PARAMETER, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface ArchivesLog {/** 要執行的操做類型好比:添加操做 **/ public String operationType() default ""; /** 要執行的操做名稱好比:添加一條用戶數據 **/ public String operationName() default ""; }(3)新建一個切面類,我叫LogAspect.java
package com.ky.zhjd.common.log;import java.lang.reflect.Method;import org.aspectj.lang.JoinPoint; import org.aspectj.lang.Signature; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.reflect.MethodSignature; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component;/*** 切面類*/ @Aspect @Component("logAspect") public class LogAspect {private static final Logger log = LoggerFactory.getLogger(LogAspect.class);// 配置織入點@Pointcut("@annotation(ArchivesLog)")public void logPointCut() {}/*** 前置通知 用于攔截操做,在方法返回后執行* * @param joinPoint 切點*/@AfterReturning(pointcut = "logPointCut()")public void doBefore(JoinPoint joinPoint) {handleLog(joinPoint, null);}/*** 攔截異常操做,有異常時執行* * @param joinPoint* @param e*/@AfterThrowing(value = "logPointCut()", throwing = "e")public void doAfter(JoinPoint joinPoint, Exception e) {handleLog(joinPoint, e);}private void handleLog(JoinPoint joinPoint, Exception e) {try {// 得到注解ArchivesLog controllerLog = getAnnotationLog(joinPoint);System.out.println("---------------自定義注解:" + controllerLog);if (controllerLog == null) {return;}// 得到方法名稱String className = joinPoint.getTarget().getClass().getName();String methodName = joinPoint.getSignature().getName();String type = controllerLog.operationType();String name = controllerLog.operationName();// 打印日志 這里能夠進行插入數據庫操做log.info(">>>>>>>>>>>>>操做類型:", type);log.info(">>>>>>>>>>>>>操做名稱:", name);log.info(">>>>>>>>>>>>>類名:", className);log.info(">>>>>>>>>>>>>方法名:", methodName);} catch (Exception exp) {// 記錄本地異常日志log.error("==前置通知異常==");log.error("異常信息:", exp.getMessage());exp.printStackTrace();}}/*** 是否存在注解,若是存在就獲取*/private static ArchivesLog getAnnotationLog(JoinPoint joinPoint) throws Exception {Signature signature = joinPoint.getSignature();MethodSignature methodSignature = (MethodSignature) signature;Method method = methodSignature.getMethod();if (method != null) {// 拿到自定義注解中的信息return method.getAnnotation(ArchivesLog.class);}return null;} }(4)在方法上使用注解 , 而后調用該方法(這里在Controller層進行操作,也可以在Service層操作)
@ArchivesLog(operationType="查詢操做",operationName="查詢一條用戶詳情")@RequestMapping(value = "/findByid", produces={"application/json;charset=UTF-8"})public @ResponseBody BaseResult<Object> findByid(String id) {String s="11";BaseResult<Object> r=userService.findById(s);System.out.println(r+">>>>>>>>>>");return r;}ok 上效果:
有什么不完善的地方歡迎指出,一塊兒學習
總結
以上是生活随笔為你收集整理的java 自定义注解+AOP实现日志记录的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: INTERSPEECH 2020 Aut
- 下一篇: 第四范式连续两年入选CB Insight