SpringBoot基础之AOP&AspectJ

日志切面,其中execution中可以改造为@Before("execution( (..))"),第一个代表返回类型,第二个代表方法名,括号中的点代表数个参数
JoinPoint可以获取到执行的方法名称。@Before("execution( hello())")表示带有一个任何类型并且返回参数不限的hello方法

@Component @Aspect public class TracingAspect { Logger logger = Logger.getLogger("..."); //执行方法前可以截获,可以控制程序不进入方法 @Before("execution(void doSomething())") //@Before("execution(* *(..))") public void entering(JoinPoint joinPoint){ logger.info("entering method"+joinPoint.getStaticPart().getSignature().toString()); } //执行方法后可以截获,可以获取到结果,异常等 @After("execution(* *(..))") public void exiting(JoinPoint joinPoint){ logger.info("existing "+joinPoint.getSignature()); for(Object org:joinPoint.getArgs()) logger.info("Arg: "+org); } //捕获异常 @AfterThrowing(pointcut = "execution(void throwsRuntimeException())", throwing = "ex") public void logException(RuntimeException ex){ logger.info("Exception:" + ex); } //捕获返回结果 @AfterReturning(pointcut = "execution(* *(..))", returning = "string") public void logResult(String string){ logger.info("result:" + string); } //同时支持进入方法前,执行方法后,捕获异常,捕获返回结果 @Around("execution(* *(..))") public Object trace(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{ String methodInformation = proceedingJoinPoint.getStaticPart().getSignature().toString(); logger.info("Entering:"+methodInformation); try{ return proceedingJoinPoint.proceed(); }catch(Throwable ex){ logger.info("Exception in:"+methodInformation + ex); throwex; }finally { logger.info("Exiting "+methodInformation); } } }

【SpringBoot基础之AOP&AspectJ】execution( (..))表示同一个package路径下
//可以在execution中写好绝对的类名方法名称也可 execution(int com.test.Service.hello(int)) //通过符号替换相应的信息,其中..表示任何子包 execution(* com.test..*Service.*(..))

如果需要截取带注解的
//必须是带方法注解的 @Around("execution(@annotation.Trace * *(..))") //必须是带类注解的 @Around("execution(* (@org.springframework.stereotype.Repository *).*(..))")

如果需要截取带注解的类
@Around("bean(*Service)") @Around("bean(*)")

通过或者来多增加不同的截取
execution(* service.*.*(..))||execution(* repository.*.*(..))

Pointcut可以替换原有的
@Around("bean(*Service)") //上面与下面的等价 package com.pluralsight.mypointcuts; public class MyPointCusts { @Pointcut("bean(*Service)") public void beanNamePointcust(){} //表示类注解截获 @Pointcut("execution(* (@org.springframework.stereotype.Repository *).*(..))") public void Repository(){} } @Around("com.pluralsight.mypointcuts.MyPointCusts.beanNamePointcust()")

允许AspectJ动态加载EnableLoadTimeWeaving
@Configuration @ComponentScan(basePackages = "com.pluralsight") @EnableLoadTimeWeaving public class SystemConfiguration { }

还有很多Spring已经定义好的Interceptor
CustomizableTraceInterceptor可自定义跟踪输出
SimpleTraceInterceptor获取基本信息
DebugInterceptor获取完整信息
PerformanceMonitorInterceptor使用StopWatch的Spring使用累,可用于测量性能,可以精确到毫秒级,适用于数据
AsyncExecutionInterceptor允许异步方法调用,可以使用这个拦截器而不用使用异步,并且方法将有后台中的其他线程执行
ConcurrencyThrottleInterceptor可以限制对象中的线程数,实际可以设置并执行的线程数
CatchInterceptor允许缓存方法的调用结果,不需要编写自己的缓存
重试机制
@Around("execution(* com.pluralsight..*Service.*(..))") public Object retry(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { try { return proceedingJoinPoint.proceed(); } catch (Throwable ex) { return proceedingJoinPoint.proceed(); } }

熔断机制,当请求CircuitBreaker的方法时,如果可以正常返回不做处理,因为counter就是0,可以直接执行
但是当获取到异常时,设置counter值为1,这样下一次再来请求则不会调用CircuitBreaker的方法,只会增加counter的值,并判断
直到counter的值为10,则调用CircuitBreaker的方法,如果成功设置counter为0可以继续调用,如果异常同样设置counter为1,再循环10次
@Component @Aspect("perthis(com.pluralsight.aspect.CircuitBreakerAspect.circuitBreakerMethods())") public class CircuitBreakerAspect { @Pointcut("execution(@com.pluralsight.aspect.CircuitBreaker * *(..))") public void circuitBreakerMethods(){} private AtomicInteger counter = new AtomicInteger(); private Throwable throwable; @Around("com.pluralsight.aspect.CircuitBreakerAspect.circuitBreakerMethods()") public Object retry(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{ try{ if(counter.get() == 0){ return proceedingJoinPoint.proceed(); } if(counter.incrementAndGet() == 10) { Object result = proceedingJoinPoint.proceed(); counter.set(0); return result; } }catch(Throwable throwable){ this.throwable = throwable; counter.set(1); } throw this.throwable; } }

    推荐阅读