Java高级架构程序员

05 使用AOP获取方法调用信息

2018-01-13  本文已影响136人  幽暗金

使用AOP获取服务层方法调用信息

通过前面章节的学习,相信大家已经对AOP有了一定的了解。
在这一章节中,将会教大家怎么使用AOP来监控Service层方法的调用,用日志输出调用参数以及方法调用时间等。
可以方便调试,及性能调优等。

创建AOP

  1. 切点的选择
    在Spring开发中,服务层一般是放在同一个包里,这个时候我们可以使用这种切点方式:

    execution(* com.learn.service..*(..))
    

    但是不排除某些情况下,服务分散到不同的包中,这个时候我们可以采用另一种方式,通过注解来使用AOP:

    @within(org.springframework.stereotype.Service)
    

    @target(org.springframework.stereotype.Service)
    

    @within和@target的使用可以回顾一下前面的章节

  2. 使用通知
    为了达到可以计算调用服务层方法执行时间的目的,我们在这里可以使用环绕通知的形式,当然,如果不需要计算方法执行时间的话,可以使用前置通知或者后置通知的方式。
    通知的使用可以回顾一下AOP五种通知详解

    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    
    @Around(value = "@target(org.springframework.stereotype.Service)")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        Object result;
        long time1 = System.currentTimeMillis();
        try {
            result = pjp.proceed();
        } catch (Throwable throwable) {
            logger.error("\n\n============================================\n"
            + "===errFunc:" + pjp.getSignature()
            + "\n===params:" + Arrays.toString(pjp.getArgs())
            + "\n============================================\n");
            throw throwable;
        }
        long time2 = System.currentTimeMillis();
        logger.info("\n\n============================================\n"
        + "===func:" + pjp.getSignature()
        + "\n===params:" + Arrays.toString(pjp.getArgs())
        + "\n===time:" + (time2-time1) + "ms"
        + "\n===result:" + result
        + "\n============================================\n");
        return result;
    }
    

    到这里,AOP就算写好了,下面我们来测试一下。

测试

  1. 创建接口

    public interface IHelloService {
        void sayHello();
    
        void say(String msg);
    
        String err(boolean isThrow);
    }
    
  2. 创建其实现类

    @Service
    public class HelloServiceImpl implements IHelloService {
        @Override
        public void sayHello() {
            System.out.println("hello");
        }
    
        @Override
        public void say(String msg) {
            System.out.println(msg);
        }
    
        @Override
        public String err(boolean isThrow) {
            System.out.println("error begin");
            if (isThrow) {
                throw new RuntimeException("sss");
            }
            return "this is an error";
        }
    }
    
  3. 创建测试用例

    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class ApplicationTests {
    
        @Resource
        private IHelloService helloService;
    
        @Test
        public void test1() {
            helloService.sayHello();
        }
    
        @Test
        public void test2() {
            helloService.say("hello");
        }
    
        @Test
        public void test3() {
            helloService.err(true);
        }
    
        @Test
        public void test4() {
            helloService.err(false);
        }
    
    }
    

    执行test1可以得到结果:

    
    ============================================
    ===func:void com.learn.service.IHelloService.sayHello()
    ===params:[]
    ===time:0ms
    ===result:null
    ============================================
    

    执行test2可以得到结果:

    
    ============================================
    ===func:void com.learn.service.IHelloService.say(String)
    ===params:[hello]
    ===time:0ms
    ===result:null
    ============================================
    

    执行test3可以得到结果:

    
    ============================================
    ===errFunc:String com.learn.service.IHelloService.err(boolean)
    ===params:[true]
    ============================================
    
    
    java.lang.RuntimeException: sss
    ...
    

    执行test4可以得到结果:

    
    ============================================
    ===func:String com.learn.service.IHelloService.err(boolean)
    ===params:[false]
    ===time:0ms
    ===result:this is an error
    ============================================
    

目录
源码链接

上一篇下一篇

猜你喜欢

热点阅读