專案中引入 Spring AOP 但不生效的解決方法
阿新 • • 發佈:2019-02-07
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~
掃描包下所有的路徑配置以及註解驅動配置也可以一併移過來,統一管理。