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

Spring AOP 日誌切面不生效:配置錯誤排查與修正

     編輯:程式設計綜合問答

常見錯誤原因

Spring AOP 配置看似正確,但 Advice (通知) 完全不被執行,通常源於以下幾點:

  1. Bean 未被 Spring 容器掃描: Advice 類 (如 Advisor) 必須標註 @Component 或在 XML 中宣告 <bean id="advices" class="..."/>。
  2. Pointcut 運算式不匹配: execution(* com.sunyard.cpjbxxShow.action.*.*(..)) 需精確對應目標方法的套件、類別、方法簽名。檢查實際 Controller/Service 套件路徑是否一致。
  3. 目標方法非 public / 為 final / 內部呼叫: Spring AOP 基於動態代理 (JDK Proxy 或 CGLIB),僅攔截 public 非 final 方法,且同類內部 this.method() 呼叫不會觸發代理。
  4. 缺少 <aop:aspectj-autoproxy/> 或 XML 命名空間宣告不全。

修正後的完整 XML 配置範例

<beans xmlns="https://www.springframework.org/schema/beans"
       xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="https://www.springframework.org/schema/aop"
       xsi:schemaLocation="...">

    <!-- 1. 啟用 @AspectJ 自動代理 -->
    <aop:aspectj-autoproxy proxy-target-class="true"/>

    <!-- 2. 定義 Advice Bean -->
    <bean id="logAdvice" class="com.sunyard.advice.Advisor"/>

    <!-- 3. 切面配置 -->
    <aop:config>
        <aop:aspect id="loggingAspect" ref="logAdvice">
            <!-- 請務必確認此路徑與實際 Controller 套件完全一致 -->
            <aop:pointcut id="controllerMethods" 
                expression="execution(public * com.sunyard.cpjbxxShow.action..*.*(..))"/>
            
            <aop:before pointcut-ref="controllerMethods" method="before"/>
            <aop:after pointcut-ref="controllerMethods" method="after"/>
            <aop:after-throwing pointcut-ref="controllerMethods" method="exception"/>
        </aop:aspect>
    </aop:config>
</beans>

Advisor 類關鍵點

@Component // 或 XML 宣告
public class Advisor {
    private static final Logger log = LoggerFactory.getLogger(Advisor.class);

    public void before(JoinPoint jp) {
        log.info("▶ 執行前: {}.{}", jp.getSignature().getDeclaringTypeName(), jp.getSignature().getName());
    }
    public void after(JoinPoint jp) {
        log.info("■ 執行後: {}.{}", jp.getSignature().getDeclaringTypeName(), jp.getSignature().getName());
    }
    public void exception(JoinPoint jp) {
        log.error("✖ 異常: {}.{} - {}", jp.getSignature().getDeclaringTypeName(), jp.getSignature().getName(), jp.getArgs());
    }
}

除錯技巧

  • 啟動時觀察日誌是否出現 Creating proxy for ... 字樣。
  • 在 Pointcut expression 中暫時改為 execution(* *(..)) 測試是否為路徑問題。
  • 確認目標 Bean 是否為 Singleton (預設),Prototype Bean 不會被代理。

核心口訣:Bean 註冊到位、Pointcut 路徑精確、方法 public 非 final、外部呼叫觸發代理。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved