博客
关于我
Spring AOP 实战篇
阅读量:343 次
发布时间:2019-03-04

本文共 4692 字,大约阅读时间需要 15 分钟。

Spring AOP 实战指南

HTTP 接口鉴权

在实际开发中,HTTP RESTful服务的接口通常需要对调用方进行权限校验。直接在每个接口方法中进行权限验证虽然可行,但会导致代码冗余和潜在错误风险。为了更优雅地解决这个问题,我们可以使用Spring AOP来实现权限校验。

实现思路

  • 定制一个AuthChecker注解,用于标注需要权限校验的方法。
  • 使用Spring AOP的@Around注解,匹配标注了AuthChecker的方法。
  • 在advice中检查调用方的Cookie中是否存在合法的user_token,如果存在则允许访问,否则返回权限错误。
  • 代码示例

    @Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public @interface AuthChecker {}@Component@Aspectpublic class HttpAopAdviseDefine {    @Pointcut("@annotation(com.xys.demo1.AuthChecker)")    public void pointcut() {}    @Around("pointcut()")    public Object checkAuth(ProceedingJoinPoint joinPoint) throws Throwable {        HttpServletRequest request = RequestContextHolder.getRequestAttributes().getRequest();        String token = getUserToken(request);        if (!token.equalsIgnoreCase("123456")) {            return "权限不合法!";        }        return joinPoint.proceed();    }    private String getUserToken(HttpServletRequest request) {        Cookie[] cookies = request.getCookies();        if (cookies == null) {            return "";        }        for (Cookie cookie : cookies) {            if (cookie.getName().equalsIgnoreCase("user_token")) {                return cookie.getValue();            }        }        return "";    }}

    使用示例

    @RestControllerpublic class DemoController {    @RequestMapping("/aop/http/alive")    public String alive() {        return "服务一切正常";    }    @AuthChecker    @RequestMapping("/aop/http/user_info")    public String callSomeInterface() {        return "调用了 user_info 接口。";    }}

    方法调用日志

    记录方法调用的日志是开发和维护服务的重要需求。我们可以使用Spring AOP的before、afterReturning和afterThrowing方法来实现日志记录。

    实现思路

  • 定义一个LogAopAdviseDefine类,使用@Before@AfterReturning@AfterThrowing注解。
  • 在before advice中记录方法调用参数。
  • 在afterReturning advice中记录方法返回结果。
  • 在afterThrowing advice中记录方法抛出的异常信息。
  • 代码示例

    @Component@Aspectpublic class LogAopAdviseDefine {    private Logger logger = LoggerFactory.getLogger(getClass());    @Pointcut("within(NeedLogService)")    public void pointcut() {}    @Before("pointcut()")    public void logMethodInvokeParam(JoinPoint joinPoint) {        logger.info("---Before method {} invoke, param: {}---", joinPoint.getSignature().toShortString(), joinPoint.getArgs());    }    @AfterReturning(pointcut = "pointcut()", returning = "retVal")    public void logMethodInvokeResult(JoinPoint joinPoint, Object retVal) {        logger.info("---After method {} invoke, result: {}---", joinPoint.getSignature().toShortString(), joinPoint.getArgs());    }    @AfterThrowing(pointcut = "pointcut()", throwing = "exception")    public void logMethodInvokeException(JoinPoint joinPoint, Exception exception) {        logger.info("---method {} invoke exception: {}---", joinPoint.getSignature().toShortString(), exception.getMessage());    }}

    使用示例

    @Servicepublic class NeedLogService {    private Logger logger = LoggerFactory.getLogger(getClass());    private Random random = new Random(System.currentTimeMillis());    public int logMethod(String someParam) {        logger.info("---NeedLogService: logMethod invoked, param: {}---", someParam);        return random.nextInt();    }    public void exceptionMethod() throws Exception {        logger.info("---NeedLogService: exceptionMethod invoked---");        throw new Exception("Something bad happened!");    }}

    方法耗时统计

    在服务监控中,记录方法调用耗时是非常重要的。我们可以使用Spring AOP的@Around注解来实现耗时统计。

    实现思路

  • 定义一个ExpiredAopAdviseDefine类,使用@Around注解。
  • 在advice中使用StopWatch记录方法执行时间。
  • 将方法执行时间上报到监控系统。
  • 代码示例

    @Component@Aspectpublic class ExpiredAopAdviseDefine {    private Logger logger = LoggerFactory.getLogger(getClass());    @Pointcut("within(SomeService)")    public void pointcut() {}    @Around("pointcut()")    public Object methodInvokeExpiredTime(ProceedingJoinPoint pjp) throws Throwable {        StopWatch stopWatch = new StopWatch();        stopWatch.start();        Object retVal = pjp.proceed();        stopWatch.stop();        reportToMonitorSystem(pjp.getSignature().toShortString(), stopWatch.getTotalTimeMillis());        return retVal;    }    private void reportToMonitorSystem(String methodName, long expiredTime) {        logger.info("---method {} invoked, expired time: {} ms---", methodName, expiredTime);    }}

    使用示例

    @Servicepublic class SomeService {    private Logger logger = LoggerFactory.getLogger(getClass());    private Random random = new Random(System.currentTimeMillis());    public void someMethod() {        logger.info("---SomeService: someMethod invoked---");        try {            Thread.sleep(random.nextInt(500));        } catch (InterruptedException e) {            e.printStackTrace();        }    }}

    总结

    通过以上几个实际场景的实现,我们可以看到Spring AOP的强大功能。无论是权限校验、日志记录还是耗时统计,Spring AOP都能以优雅的方式解决问题。如果你有更多的业务需求,可以根据实际需求灵活配置Spring AOP来实现更复杂的功能。

    转载地址:http://guie.baihongyu.com/

    你可能感兴趣的文章
    Objective-C实现SizeBalancedTree大小平衡树(附完整源码)
    查看>>
    Objective-C实现skew heap倾斜堆算法(附完整源码)
    查看>>
    Objective-C实现Skip List跳表算法(附完整源码)
    查看>>
    Objective-C实现slack message松弛消息算法(附完整源码)
    查看>>
    Objective-C实现SlopeOne算法(附完整源码)
    查看>>
    Objective-C实现slow sort慢排序算法(附完整源码)
    查看>>
    Objective-C实现smo算法(附完整源码)
    查看>>
    Objective-C实现strschr函数功能(附完整源码)
    查看>>
    Objective-C实现subset generation子集生成算法(附完整源码)
    查看>>
    Objective-C实现substring函数功能(附完整源码)
    查看>>
    Objective-C实现sum of geometric progression几何级数之和算法(附完整源码)
    查看>>
    Objective-C实现sum of subset子集总和算法(附完整源码)
    查看>>
    Objective-C实现SVM支持向量机算法(附完整源码)
    查看>>
    Objective-C实现sylvester西尔维斯特方程算法(附完整源码)
    查看>>
    Objective-C实现tabu search禁忌搜索算法(附完整源码)
    查看>>
    Objective-C实现tanh函数功能(附完整源码)
    查看>>
    Objective-C实现TCP Server 多线程同时连接多个客户端(附完整源码)
    查看>>
    Objective-C实现TCP拥塞控制(附完整源码)
    查看>>
    Objective-C实现Tenengrad梯度函数(附完整源码)
    查看>>
    Objective-C实现ternary search三元搜索算法(附完整源码)
    查看>>