项目中引入 Spring AOP 但不生效的解决方法

1 发现问题

打算使用 Spring AOP 做切面实现记录日志的功能。因为注解方式比较简单,所以采用注解来实现。

1、在 spring 的配置文件中加入了以下配置:


<context:component-scan base-package="com"/>


<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 配置文件中:


<context:component-scan base-package="com"/>


<mvc:annotation-driven/>


<aop:aspectj-autoproxy/>

重启后,运行系统,AOP 恢复正常啦:

开始
before()
...
结束

记住,如果项目用了 spring MVC,一定要把 AOP 的相关配置移动到 MVC 配置文件哦O(∩_∩)O~

扫描包下所有的路径配置以及注解驱动配置也可以一并移过来,统一管理。

你可能感兴趣的:(Java,Spring)