一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第3天,点击查看活动详情。
java中aop之advice相关注解的只用
前文
本文内容为对于aop中advice相关注解的一些使用方法的总结,主要结合项目中的引用。其中难免有不准确之处,还请见谅。
详细介绍
使用advice一般主要是采用@RestControllerAdvice。而该注解包含一些字段,则制定了其修饰的范围。例如可以指定使用了哪些注解,或在哪些包下的类才会生效,以此进行了范围的指定。而在该注解的使用过程中,需要修饰的方法对于另外的接口进行实现,也就是RequestBodyAdvice或ResponseBodyAdvice等,而他们分别表示了允许在请求信息被读取前对请求内容进行定制,以及允许在返回信息在被消息格式化类处理前,对于返回消息进行定制处理。同时在该类中通过support方法,对与修饰的范围进行限定。这样当满足对应的修饰范围时,会执行具体的方法,实现对于请求数据的定制或对于返回数据的定制。
应用示例
下面来看一个简单的返回数据定制的拦截:
@RestControllerAdvice
public class ResonseBodyResultAdvice implements ResponseBodyAdvice<Object> {
public ResonseBodyResultAdvice() {
}
public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
return AnnotatedElementUtils.hasAnnotation(returnType.getContainingClass(), ResponseBodyResult.class) || returnType.hasMethodAnnotation(ResponseBodyResult.class);
}
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
if (body instanceof Result) {
return body;
} else {
Result result = Result.builder().success(true).body(body).build();
return body instanceof String ? JsonUtils.serialize(result) : result;
}
}
}
如上图所示,我们指定了当采用ResponseBodyResult注解返回数据时,进行返回数据的格式包装,相当于对于返回数据的强化。具体来讲,也就是增加了调用结果的成功及失败信息。将方法中实际返回的值作为最终消息体的一部分,另一部分采用请求的结果进行组装,以此方便调用方对于后续结果的处理。
为什么能达到这种效果
而这个方案为什么会生效呢?我们自然会发出这个疑问。要知道这个问题的答案,需要对源码进行阅读。想知道什么之后生效,也就是知道什么时间点该方法会被执行即可,也就是需要知道beforeBodyWrite方法的调用节点。通过对于源码信息的阅读可以发现,在返回数据前会进行一个链路的查询,对于该方法进行调用,也就是决定了该方法的实际执行。
for (ResponseBodyAdvice<?> advice : getMatchingAdvice(returnType, ResponseBodyAdvice.class)) {
if (advice.supports(returnType, converterType)) {
body = ((ResponseBodyAdvice<T>) advice).beforeBodyWrite((T) body, returnType,
contentType, converterType, request, response);
}
}
后记
- 千古兴亡多少事?悠悠。不尽长江滚滚流。