1. 程式人生 > >專案中引入 Spring AOP 但不生效的解決方法

專案中引入 Spring AOP 但不生效的解決方法

1 發現問題

打算使用 Spring AOP 做切面實現記錄日誌的功能。因為註解方式比較簡單,所以採用註解來實現。

1、在 spring 的配置檔案中加入了以下配置:

<!-- 掃描包下所有的類,讓標註Spring 註解的類生效 -->
<context:component-scan base-package="com"/>

<!-- 開啟對 @Aspect 的支援-->
<aop:aspectj-autoproxy/>

2、新增了切面類:

@Component
@Aspect
public class SysLogAspect {
static Logger logger = LoggerFactory.getLogger(SysLogAspect.class); @Pointcut("@annotation(com.deniro.jail.domain.sys.SysLog)") private void sysLog() { } /** * 記錄日誌 * * @param pjp */ @Around("sysLog()") public Object log(ProceedingJoinPoint pjp) { logger.info("呼叫方法:{};輸入引數:{}"
, pjp.getSignature() , pjp .getArgs()); StopWatch sw = new StopWatch(); sw.start(); Object o = null; try { System.out.println("開始"); o = pjp.proceed(); System.out.println("結束"); } catch (Throwable throwable) { logger.error("記錄日誌"
, throwable); } sw.stop(); logger.info("輸出引數:{};耗時:{}", o, sw.toString()); return o; } }

3、新建了註解類:


public @interface SysLog {

    /**
     * 描述
     *
     * @return
     */
    public String description();
}

4、然後,在相應的方法上加入了該註解:

@RequestMapping(value = "/save")
@ResponseBody
@SysLog(description = " xxx")
public AjaxResponse save(DictItem dictItem) {
}

然而,專案在實際執行時,沒有打印出切面的日誌!

2 分析

開啟 log4j 的 DEBUG 選項,發現系統並沒有呼叫切面方法!

建一個單元測試試一試吧:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:spring-context.xml"})
@TransactionConfiguration(defaultRollback = true)
@Transactional
public class BeanAspectTest {

    @Autowired
    private DictItemController dictItemController;


    @Test
    public void aspect() {
        DictItem dictItem=new DictItem();
        dictItem.setDictItemIsOptional("true");
        dictItem.setDictItemDescription("1");
        dictItem.setDictItemValue("1");
        dictItem.setDictItemType("health");
        dictItemController.save(dictItem);
    }
}

在單元測試中,可以打印出切面日誌,這說明 spring 框架配置的 AOP 執行正常!那麼,為什麼系統執行時就不正常了呢?

比較單元測試用到的配置檔案與系統執行的配置檔案,在有一點上不同,即系統執行時使用到了 spring 的 MVC 配置檔案。spring 的 MVC 是獨立的配置檔案,所以 Controller 的配置都在這個檔案中,應該把 AOP 的配置移到這裡。

3 解決問題

把原有的配置移動到 spring 的 MVC 配置檔案中:

<!-- 掃描包下所有的類,讓標註Spring 註解的類生效 -->
<context:component-scan base-package="com"/>

<!--配置註解驅動-->
<mvc:annotation-driven/>

<!-- 開啟對 @Aspect 的支援-->
<aop:aspectj-autoproxy/>

重啟後,執行系統,AOP 恢復正常啦:

開始
before()
...
結束

記住,如果專案用了 spring MVC,一定要把 AOP 的相關配置移動到 MVC 配置檔案哦O(∩_∩)O~

掃描包下所有的路徑配置以及註解驅動配置也可以一併移過來,統一管理。