Spring AOP 的一次偷懒实践

其实场景有点儿诡异,但是关于 AOP 的部分,还是有通用性的。

一个遗留系统,我们希望对所有的 action 方法做点儿手脚,对某些情况下的入参做改写,例如 userId,如果发现请求给的 userId 不对的话,就改写成我们预建立好的匿名账号上。

如果是一两个方法就还好,直接改就行,但是有十多个的时候,就不由的想有没有偷懒的法子了,答案就是 AOP。

对所有需要改写的 Action,我们可以做一个 Around 拦截,方便我们在方法执行前,对入参做手脚,代码如下:

@Aspect
@Component
public class AroundAdvice {

    @Around("execution(* com.mmliu.controller.user.*.*(..)) && @annotation(org.springframework.web.bind.annotation.RequestMapping)")
    public Object processTx(ProceedingJoinPoint jp) throws java.lang.Throwable {
        System.out.println("执行目标方法之前...");

        MethodSignature methodSignature = (MethodSignature) jp.getSignature();
        String[] paramNames = methodSignature.getParameterNames();

        //检查参数,如果包含 userId且需要更新,则更新 userId 的值
        Object[] args = jp.getArgs();
        for(int i = 0; i < paramNames.length; i++){
            if("userId".equals(paramNames[i])){
                Object userIdObj = args[i];
                long userId = Long.valueOf(userIdObj.toString());

                if(needChangeId(userId) <= 0){
                    userId = 1000000L;
                }

                args[i] = userId;
            }
        }

        // 执行目标方法,并保存目标方法执行后的返回值
        Object rvt = jp.proceed(args);

        System.out.println("执行目标方法之后");

        return rvt;
    }
}

最关键的一步其实就是 Object rvt = jp.proceed(args); 了,这时候调用的 Action 方法的参数值 args,已经是被更新过的了。

这样,通过 AOP,我们就实现了对原有代码几乎没有侵入的情况下,更改了程序的逻辑,而且,成功的偷到了懒,不用一个方法一个方法的去修改了。

你可能感兴趣的:(Spring AOP 的一次偷懒实践)