最近我开发了一个管理系统,基本上都是CRUD操作,见下图:
GET admin/foos
GET admin/foos/{id}
POST admin/foos
PUT admin/foos
DELETE admin/foos/{id}
为了减少开发工作,我在BaseController
中加入了公共逻辑,具体的控制器扩展了BaseController,例如
public class FooController extends BaseController
public class BarController extends BaseController
它可以成功地工作,但有一个问题:为什么可以在BaseController的方法中扩展注释,而不能在BaseController本身中扩展注释?
@RestController
@Slf4j
public abstract class BaseController
@GetMapping("/{id}")
@ApiOperation(value = "detail info", notes = "")
protected ApiResult detail(@PathVariable String id) {
// ...
}
@RestController
@RequestMapping("admin/bars")
public class BarController extends BaseController{
@Override
protected ApiResult detail(String id) {
return super.detail(id);
}
}
为什么BarController不能扩展BaseController的@RestController和@Slf4j,而Override方法可以扩展@GetMapping和@ApiOperation?在我看来,Override方法将完全取代原来的方法,因此它不应该扩展父方法的注释。
@RestController
和@Slf4j
是基于类的注释,而@GetMapping
和@ApiOperation
是由@Override覆盖的基于方法的注释。
更多详细信息:https://javaee.github.io/javaee-spec/AnnotationRules
Override方法可以扩展@GetMapping和@ApiOperation,这归功于spring框架。
org.springframework.core.annotation.AnnotationsScanner#processMethodHierarchy
for (Method candidateMethod : getBaseTypeMethods(context, sourceClass, classFilter)) {
if (candidateMethod != null && isOverride(rootMethod, candidateMethod)) {
result = processMethodAnnotations(context, aggregateIndex[0],
candidateMethod, processor, classFilter);
calledProcessor = true;
if (result != null) {
return result;
}
}
}