本文讲一讲ControllerAdvice注解的讲解
首先看注解的定义
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Component public @interface ControllerAdvice {
@AliasFor("basePackages") String[] value() default {};
@AliasFor("value") String[] basePackages() default {};
Class<?>[] basePackageClasses() default {};
Class<?>[] assignableTypes() default {};
Class<? extends Annotation>[] annotations() default {}; }
|
首先,这个注解标记的类会被声明为全局异常处理器,但是它的优先级比controller中定义的ExceptionHandler注解要低。
注解内部有五个方法,其中value和basePackages是一样的。
basePackages
表示限制包名,限制controller的类的包名,必须满足匹配
basePackageClasses
类型安全的限制包名方法,框架建议在想要限制的包名内创建一个空的类,这样比上面直接使用包名字符串要好
assignableTypes
限制controller类的继承关系
annotations
限制controller上必须存在指定的注解
如果上面四个参数都没有填写,默认是匹配的。源码在下面。
ServletInvocableHandlerMethod.class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| protected ServletInvocableHandlerMethod getExceptionHandlerMethod(HandlerMethod handlerMethod, Exception exception) { Class<?> handlerType = (handlerMethod != null ? handlerMethod.getBeanType() : null);
if (handlerMethod != null) { ExceptionHandlerMethodResolver resolver = this.exceptionHandlerCache.get(handlerType); if (resolver == null) { resolver = new ExceptionHandlerMethodResolver(handlerType); this.exceptionHandlerCache.put(handlerType, resolver); } Method method = resolver.resolveMethod(exception); if (method != null) { return new ServletInvocableHandlerMethod(handlerMethod.getBean(), method); } } for (Entry<ControllerAdviceBean, ExceptionHandlerMethodResolver> entry : this.exceptionHandlerAdviceCache.entrySet()) {
if (entry.getKey().isApplicableToBeanType(handlerType)) { ExceptionHandlerMethodResolver resolver = entry.getValue(); Method method = resolver.resolveMethod(exception); if (method != null) { return new ServletInvocableHandlerMethod(entry.getKey().resolveBean(), method); } } } return null; }
|
匹配逻辑源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
|
public boolean isApplicableToBeanType(Class<?> beanType) {
if (!hasSelectors()) { return true; } else if (beanType != null) {
for (String basePackage : this.basePackages) { if (beanType.getName().startsWith(basePackage)) { return true; } }
for (Class<?> clazz : this.assignableTypes) { if (ClassUtils.isAssignable(clazz, beanType)) { return true; } }
for (Class<? extends Annotation> annotationClass : this.annotations) { if (AnnotationUtils.findAnnotation(beanType, annotationClass) != null) { return true; } } } return false; }
private boolean hasSelectors() { return (!this.basePackages.isEmpty() || !this.assignableTypes.isEmpty() || !this.annotations.isEmpty()); }
|