首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Spring AOP + Log4j 註解式日誌切面:精準攔截指定方法記錄出入參變更

     編輯:Java 綜合教學

Spring AOP + Log4j 註解式日誌切面:精準攔截指定方法記錄出入參變更

利用 Spring AOP 的 @Aspect 與 execution 切點表達式,結合 Log4j 實現無侵入式業務日誌記錄。本文展示如何精準攔截 Service 層特定方法,記錄修改前後的實體快照與操作人信息。

一、切點表達式語法速查

execution(* com.example.service.impl..PromoteServiceImpl.updatePromote(..))
片段含義
execution切點函數,匹配方法執行
* (第一個)返回類型任意
com.example.service.impl..包路徑,.. 表示當前包及所有子包
PromoteServiceImpl目標類名
updatePromote目標方法名
(..)任意參數列表

二、切面類實現

@Component
@Aspect
public class ServiceAspect extends BaseAction<Object> {
    private static final Logger log = Logger.getLogger(ServiceAspect.class);
    @Autowired private PromoteService promoteService;

    @Pointcut("execution(* com.example.service.impl..PromoteServiceImpl.updatePromote(..))")
    public void updatePromotePointcut() {}

    @Before("updatePromotePointcut()")
    public void before(JoinPoint jp) {
        Object[] args = jp.getArgs(); // [PromoteVO, Long promoteId]
        Long id = (Long) args[1];
        PromoteVO before = promoteService.queryPromoteDetail(id);
        SessionInfo si = (SessionInfo) getSession().getAttribute("sessionInfo");
        log.info("【修改活動】時間:{} 用戶:{} 賬號:{}", new Date(), si.getUserName(), si.getUserAcct());
        log.info("修改前: {}", before);
    }

    @After("updatePromotePointcut()")
    public void after(JoinPoint jp) {
        Object[] args = jp.getArgs();
        Long id = (Long) args[1];
        PromoteVO after = promoteService.queryPromoteDetail(id);
        log.info("修改後: {}", after);
    }
}

三、Spring AOP 啟用配置

<beans xmlns:aop="https://www.springframework.org/schema/aop" ...>
    <aop:aspectj-autoproxy proxy-target-class="true" /> <!-- 支援類代理 -->
</beans>

四、關鍵注意事項

  1. 自調用不生效:類內部方法互調不會觸發代理,需注入自身或拆分 Bean
  2. 參數獲取:JoinPoint.getArgs() 返回陣列,須按簽名順序強轉
  3. 事務邊界:@Before 在事務開啟前,@AfterReturning 在提交後,若需事務內數據請用 @Around 手動控制
  4. 性能:切面邏輯應極輕量,避免複雜查詢阻塞主業務;大對象序列化日誌考慮異步寫入
  5. 異常處理:切面內異常不應拋出,防止影響主流程,建議 try-catch 吞噬並記錄錯誤日誌

五、進階:環繞通知實現耗時統計

@Around("updatePromotePointcut()")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
    long start = System.currentTimeMillis();
    try { return pjp.proceed(); }
    finally { log.info("updatePromote 耗時: {}ms", System.currentTimeMillis() - start); }
}
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved