使用AOP獲取服務(wù)層方法調(diào)用信息
通過(guò)前面章節(jié)的學(xué)習(xí)即碗,相信大家已經(jīng)對(duì)AOP有了一定的了解乾翔。
在這一章節(jié)中告嘲,將會(huì)教大家怎么使用AOP來(lái)監(jiān)控Service層方法的調(diào)用赏殃,用日志輸出調(diào)用參數(shù)以及方法調(diào)用時(shí)間等稳强。
可以方便調(diào)試场仲,及性能調(diào)優(yōu)等和悦。
創(chuàng)建AOP
-
切點(diǎn)的選擇
在Spring開發(fā)中,服務(wù)層一般是放在同一個(gè)包里燎窘,這個(gè)時(shí)候我們可以使用這種切點(diǎn)方式:execution(* com.learn.service..*(..))
但是不排除某些情況下摹闽,服務(wù)分散到不同的包中,這個(gè)時(shí)候我們可以采用另一種方式褐健,通過(guò)注解來(lái)使用AOP:
@within(org.springframework.stereotype.Service)
或
@target(org.springframework.stereotype.Service)
@within和@target的使用可以回顧一下前面的章節(jié)
-
使用通知
為了達(dá)到可以計(jì)算調(diào)用服務(wù)層方法執(zhí)行時(shí)間的目的付鹿,我們?cè)谶@里可以使用環(huán)繞通知的形式,當(dāng)然蚜迅,如果不需要計(jì)算方法執(zhí)行時(shí)間的話舵匾,可以使用前置通知或者后置通知的方式。
通知的使用可以回顧一下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就算寫好了坐梯,下面我們來(lái)測(cè)試一下。
測(cè)試
-
創(chuàng)建接口
public interface IHelloService { void sayHello(); void say(String msg); String err(boolean isThrow); }
-
創(chuàng)建其實(shí)現(xiàn)類
@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"; } }
-
創(chuàng)建測(cè)試用例
@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); } }
執(zhí)行test1可以得到結(jié)果:
============================================ ===func:void com.learn.service.IHelloService.sayHello() ===params:[] ===time:0ms ===result:null ============================================
執(zhí)行test2可以得到結(jié)果:
============================================ ===func:void com.learn.service.IHelloService.say(String) ===params:[hello] ===time:0ms ===result:null ============================================
執(zhí)行test3可以得到結(jié)果:
============================================ ===errFunc:String com.learn.service.IHelloService.err(boolean) ===params:[true] ============================================ java.lang.RuntimeException: sss ...
執(zhí)行test4可以得到結(jié)果:
============================================ ===func:String com.learn.service.IHelloService.err(boolean) ===params:[false] ===time:0ms ===result:this is an error ============================================