SpringAOP实战应用

Springboot中使用AOP特性非常简单,使用@AspectJ注解,然后再配置中开启AspectJ即可。在日常的应用,有时可以将日志记录和异常处理在一个拦截器中统一处理,但有时在项目中无法通过一个拦截器解决所有切面问题,此时,就需要将日志、异常处理等拦截器功能拆分开来,但有一点是相同的,就是在需要时增加一个抽象层次用于拦截。

基础知识

这部分的细节主要是注解的使用,可以参看之后示例。 参考资料 http://www.cnblogs.com/best/p/5736422.html

实践

AOP配置

@Configuration
@EnableAspectJAutoProxy
public class AOPConfig {
}

Log(AOP)实例

@Aspect
@Component
public final class LogInterceptor {
    private final static int DEFAULT_MAX_LOG_LENGTH = 8192;

    @Pointcut("execution(*  com.bjork.ws.XXXWSImplForSpring.*(..))")
    public void serviceMethodPointcut() {
    }

    @Pointcut("execution( * com.bjork.ws.agent..*.*(..)) && @annotation(com.bjork.ws.core.AgentOriginalMethod)")
    public void agentOriginalMethodPointcut() {
    }

    @Around("serviceMethodPointcut() || agentOriginalMethodPointcut()")
    // @Around("agentOriginalMethodPointcut()")
    public Object Interceptor(ProceedingJoinPoint pjp) throws Throwable {
        // 获取aop相关信息
        Signature signature = pjp.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method targetMethod = methodSignature.getMethod();
        Class<?> returnType = targetMethod.getReturnType();
        Object result = null;
        Logger logger = LoggerFactory.getLogger(pjp.getTarget().getClass());

        try {
            // 设置默认返回值
            result = returnType.newInstance();

            logger.info(String.format("%s方法调用开始!", targetMethod.getName()));
            // 约定只有一个参数
            Object uniqueParameter = pjp.getArgs()[0];
            logRequest(JsonHelper.serialize(uniqueParameter), logger);
            result = pjp.proceed();
            logResponse(JsonHelper.serialize(result), logger);
        } finally {
            logger.info(String.format("%s方法调用结束!", targetMethod.getName()));
        }
        return result;
    }

    protected void logRequest(String requestString, Logger logger) {
        if (requestString.length() <= DEFAULT_MAX_LOG_LENGTH)
            logger.info(String.format("请求体为:%s", requestString));
    }

    protected void logResponse(String responseString, Logger logger) {
        if (responseString.length() <= DEFAULT_MAX_LOG_LENGTH)
            logger.info(String.format("响应体为:%s", responseString));
    }
}

Exception (AOP)实例

@Aspect
@Component
public final class ServiceInterceptor {
    @Pointcut("execution(* com.bjork.ws.service..*(..)) "
        + "&& @annotation(com.bjork.ws.core.ServiceOpenMethod)")
    public void serviceMethodPointcut() {
    }

    @Around("serviceMethodPointcut()")
    public GenericResult Interceptor(ProceedingJoinPoint pjp) {
        // 获取aop相关信息
        Signature signature = pjp.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method targetMethod = methodSignature.getMethod();
        // Class<?> returnType = targetMethod.getReturnType();
        GenericResult result = new GenericResult();
        Logger logger = LoggerFactory.getLogger(pjp.getTarget().getClass());

        try {
            // 设置默认返回值
            // result = returnType.newInstance();

            // 约定只有一个参数
            Object uniqueParameter = pjp.getArgs()[0];
            result = (GenericResult) pjp.proceed();
        } catch (ValidException vex) {
            result.getResultInfo().setIsSuccessful(false);
            result.getResultInfo().setCode(vex.getErrorCode());
            result.getResultInfo().setMessage(vex.getMessage());
            logger.info(vex.getMessage());
        } catch (BizException bex) {
            result.getResultInfo().setIsSuccessful(false);
            result.getResultInfo().setCode(bex.getErrorCode());
            result.getResultInfo().setMessage(bex.getMessage());
            logger.warn(bex.getMessage());
        } catch (ExternalCallException ecex) {
            result.getResultInfo().setIsSuccessful(false);
            result.getResultInfo().setCode(ecex.getErrorCode());
            result.getResultInfo().setMessage(ecex.getMessage());
            logger.warn(ecex.getMessage());
        } catch (Throwable ex) {
            result.getResultInfo().setIsSuccessful(false);
            result.getResultInfo().setCode(ExceptionInfo.SYSTEM_EXCEPTION_CODE);
            result.getResultInfo().setMessage(ExceptionInfo.SYSTEM_EXCEPTION_MESSAGE);
            logger.error(ex.getMessage(), ex);
        } finally {
        }
        return result;
    }
}

AutoConfiguration配置

@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
//@SpringBootApplication
@ComponentScan("com.xxx.ws")
public class ServiceInitializer extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(ServiceInitializer.class);
    }

    @Bean
    public LogAspect logAspect() {
        return new LogAspect();
    }

    @Bean
    public ServiceExceptionAspect serviceExceptionAspect() {
        return new ServiceExceptionAspect();
    }
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏码匠的流水账

聊聊storm的tickTuple

storm-2.0.0/storm-client/src/jvm/org/apache/storm/utils/TupleUtils.java

1212
来自专栏闻道于事

Spring框架(三) JDBCTemplate,声明式事务,自动装载(注解)

 JDBCTemplate 按照标准正常项目的结构 结构图: ? model层 dao层 实现  dao:(DateBase Access Object) 数据...

7819
来自专栏码匠的流水账

聊聊JvmGcMetrics的managementExtensionsPresent

本文主要研究下JvmGcMetrics的managementExtensionsPresent

1201
来自专栏源码之家

EXCEL密码去除(工作表、工作薄密码保护破解)

28311
来自专栏java、Spring、技术分享

Spring MVC ControllerAdvice深入解析

  Spring 在3.2版本后面增加了一个ControllerAdvice注解。网上的资料说的都是ControllerAdvice配合ExceptionHan...

3771
来自专栏名山丶深处

springaop——AspectJ不可不知的细节

5885
来自专栏名山丶深处

springaop——AspectJ不可不知的细节

1557
来自专栏Hongten

原创Java版的Shell

如果你接触过windows操作系统,你应该对windows中的cmd有一定的了解。

1514
来自专栏精讲JAVA

接口方法上的注解无法被 @Aspect 声明的切面拦截的原因分析

在Spring中使用MyBatis的Mapper接口自动生成时,用一个自定义的注解标记在Mapper接口的方法中,再利用@Aspect定义一个切面,拦截这个注解...

3362
来自专栏码匠的流水账

聊聊HystrixCircuitBreaker

hystrix-core-1.5.12-sources.jar!/com/netflix/hystrix/HystrixCircuitBreaker.java

801

扫码关注云+社区

领取腾讯云代金券