使用AOP获取服务层方法调用信息
通过前面章节的学习,相信大家已经对AOP有了一定的了解。
在这一章节中,将会教大家怎么使用AOP来监控Service层方法的调用,用日志输出调用参数以及方法调用时间等。
可以方便调试,及性能调优等。
创建AOP
-
切点的选择
在Spring开发中,服务层一般是放在同一个包里,这个时候我们可以使用这种切点方式:execution(* com.learn.service..*(..))
但是不排除某些情况下,服务分散到不同的包中,这个时候我们可以采用另一种方式,通过注解来使用AOP:
@within(org.springframework.stereotype.Service)
或
@target(org.springframework.stereotype.Service)
@within和@target的使用可以回顾一下前面的章节
-
使用通知
为了达到可以计算调用服务层方法执行时间的目的,我们在这里可以使用环绕通知的形式,当然,如果不需要计算方法执行时间的话,可以使用前置通知或者后置通知的方式。
通知的使用可以回顾一下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就算写好了,下面我们来测试一下。
测试
-
创建接口
public interface IHelloService { void sayHello(); void say(String msg); String err(boolean isThrow); }
-
创建其实现类
@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"; } }
-
创建测试用例
@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 ============================================