Spring Controller注解的核心作用
Spring MVC中的@Controller注解是构建Web应用的基石。它不仅仅是一个简单的标记,背后蕴含着Spring框架强大的组件扫描、依赖注入和请求映射机制。
在现代微服务架构中,理解Controller注解的底层原理对于构建高性能、可维护的REST API至关重要。
注解的元数据定义
@Controller注解的源码定义揭示了其本质:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Controller {
@AliasFor(annotation = Component.class)
String value() default "";
}关键元注解解析
| 元注解 | 作用 | 影响范围 |
|---|---|---|
@Target(ElementType.TYPE) | 限定注解只能用于类级别 | 编译时检查 |
@Retention(RetentionPolicy.RUNTIME) | 注解信息保留到运行时 | 反射可访问 |
@Component | 标识为Spring组件 | 自动扫描注册 |
@Documented | 包含在JavaDoc中 | API文档生成 |
组件扫描的工作机制
Spring容器启动时,ComponentScanAnnotationParser负责解析配置类上的@ComponentScan注解:
public class ComponentScanAnnotationParser {
public Set<BeanDefinitionHolder> parse(
AnnotationAttributes componentScan,
final String declaringClass) {
// 创建ClassPathBeanDefinitionScanner
ClassPathBeanDefinitionScanner scanner =
new ClassPathBeanDefinitionScanner(
this.registry,
componentScan.getBoolean("useDefaultFilters"),
this.environment,
this.resourceLoader
);
// 设置扫描过滤器
Class<? extends Annotation>[] includeFilters =
componentScan.getClassArray("includeFilters");
for (Class<? extends Annotation> filterType : includeFilters) {
scanner.addIncludeFilter(
new AnnotationTypeFilter(filterType)
);
}
// 执行扫描
return scanner.doScan(
StringUtils.toStringArray(basePackages)
);
}
}扫描流程序列图
BeanDefinition的创建过程
当扫描器发现带有@Controller注解的类时,会创建对应的BeanDefinition:
public class AnnotatedBeanDefinitionReader {
private <T> void doRegisterBean(
Class<T> beanClass,
String name,
Class<? extends Annotation>[] qualifiers,
Supplier<T> supplier,
BeanDefinitionCustomizer[] customizers) {
// 创建AnnotatedGenericBeanDefinition
AnnotatedGenericBeanDefinition abd =
new AnnotatedGenericBeanDefinition(beanClass);
// 判断是否需要跳过
if (this.conditionEvaluator.shouldSkip(
abd.getMetadata())) {
return;
}
// 设置实例供应器
abd.setInstanceSupplier(supplier);
// 解析作用域
ScopeMetadata scopeMetadata =
this.scopeMetadataResolver.resolveScopeMetadata(abd);
abd.setScope(scopeMetadata.getScopeName());
// 生成Bean名称
String beanName = (name != null ? name :
this.beanNameGenerator.generateBeanName(abd, this.registry));
// 处理通用注解
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
// 注册到容器
BeanDefinitionHolder definitionHolder =
new BeanDefinitionHolder(abd, beanName);
definitionHolder = AnnotationConfigUtils
.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
BeanDefinitionReaderUtils.registerBeanDefinition(
definitionHolder, this.registry);
}
}请求映射的注册机制
RequestMappingHandlerMapping负责处理@RequestMapping及其组合注解:
public class RequestMappingHandlerMapping
extends RequestMappingInfoHandlerMapping
implements MatchableHandlerMapping, EmbeddedValueResolverAware {
@Override
protected void detectHandlerMethods(Object handler) {
Class<?> handlerType = (handler instanceof String ?
obtainApplicationContext().getType((String) handler) :
handler.getClass());
if (handlerType != null) {
Class<?> userType = ClassUtils.getUserClass(handlerType);
// 查找所有方法的映射
Map<Method, T> methods = MethodIntrospector.selectMethods(userType,
(MethodIntrospector.MetadataLookup<T>) method -> {
try {
return getMappingForMethod(method, userType);
}
catch (Throwable ex) {
throw new IllegalStateException(
"Invalid mapping on handler class [" +
userType.getName() + "]: " + method, ex);
}
});
// 注册每个方法的映射
methods.forEach((method, mapping) -> {
Method invocableMethod = AopUtils.selectInvocableMethod(
method, userType);
registerHandlerMethod(handler, invocableMethod, mapping);
});
}
}
private RequestMappingInfo getMappingForMethod(
Method method, Class<?> handlerType) {
// 获取方法级别的@RequestMapping
RequestMappingInfo info = createRequestMappingInfo(method);
if (info != null) {
// 获取类级别的@RequestMapping
RequestMappingInfo typeInfo =
createRequestMappingInfo(handlerType);
if (typeInfo != null) {
// 合并类和方法的映射信息
info = typeInfo.combine(info);
}
String prefix = getPathPrefix(handlerType);
if (prefix != null) {
info = RequestMappingInfo.paths(prefix).build().combine(info);
}
}
return info;
}
}HandlerAdapter的执行流程
当请求到达时,RequestMappingHandlerAdapter负责调用Controller方法:
public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter
implements BeanFactoryAware, InitializingBean {
@Override
protected ModelAndView handleInternal(
HttpServletRequest request,
HttpServletResponse response,
HandlerMethod handlerMethod) throws Exception {
ModelAndView mav;
checkRequest(request);
// 执行Controller方法
if (this.synchronizeOnSession) {
HttpSession session = request.getSession(false);
if (session != null) {
Object mutex = WebUtils.getSessionMutex(session);
synchronized (mutex) {
mav = invokeHandlerMethod(
request, response, handlerMethod);
}
}
else {
mav = invokeHandlerMethod(
request, response, handlerMethod);
}
}
else {
mav = invokeHandlerMethod(
request, response, handlerMethod);
}
// 处理缓存控制
if (!response.containsHeader(HEADER_CACHE_CONTROL)) {
if (getSessionAttributesHandler(handlerMethod)
.hasSessionAttributes()) {
applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
}
else {
prepareResponse(response);
}
}
return mav;
}
private ModelAndView invokeHandlerMethod(
HttpServletRequest request,
HttpServletResponse response,
HandlerMethod handlerMethod) throws Exception {
ServletWebRequest webRequest = new ServletWebRequest(request, response);
try {
// 创建数据绑定工厂
WebDataBinderFactory binderFactory =
getDataBinderFactory(handlerMethod);
// 创建模型工厂
ModelFactory modelFactory =
getModelFactory(handlerMethod, binderFactory);
// 创建可调用的方法
ServletInvocableHandlerMethod invocableMethod =
createInvocableHandlerMethod(handlerMethod);
if (this.argumentResolvers != null) {
invocableMethod.setHandlerMethodArgumentResolvers(
this.argumentResolvers);
}
if (this.returnValueHandlers != null) {
invocableMethod.setHandlerMethodReturnValueHandlers(
this.returnValueHandlers);
}
invocableMethod.setDataBinderFactory(binderFactory);
invocableMethod.setParameterNameDiscoverer(
this.parameterNameDiscoverer);
// 创建ModelAndViewContainer
ModelAndViewContainer mavContainer = new ModelAndViewContainer();
mavContainer.addAllAttributes(
RequestContextUtils.getInputFlashMap(request));
modelFactory.initModel(webRequest, mavContainer, invocableMethod);
mavContainer.setIgnoreDefaultModelOnRedirect(
this.ignoreDefaultModelOnRedirect);
// 异步请求处理
AsyncWebRequest asyncWebRequest =
WebAsyncUtils.createAsyncWebRequest(request, response);
asyncWebRequest.setTimeout(this.asyncRequestTimeout);
// 执行方法调用
invocableMethod.invokeAndHandle(
webRequest, mavContainer);
if (asyncManager.isConcurrentHandlingStarted()) {
return null;
}
return getModelAndView(mavContainer, modelFactory, webRequest);
}
finally {
webRequest.requestCompleted();
}
}
}参数解析器的工作原理
HandlerMethodArgumentResolver接口定义了参数解析的标准:
public interface HandlerMethodArgumentResolver {
boolean supportsParameter(MethodParameter parameter);
Object resolveArgument(
MethodParameter parameter,
ModelAndViewContainer mavContainer,
NativeWebRequest webRequest,
WebDataBinderFactory binderFactory) throws Exception;
}
// RequestParam参数解析器实现
public class RequestParamMethodArgumentResolver
extends AbstractNamedValueMethodArgumentResolver
implements UriComponentsContributor {
@Override
public boolean supportsParameter(MethodParameter parameter) {
if (parameter.hasParameterAnnotation(RequestParam.class)) {
if (Map.class.isAssignableFrom(parameter.nestedIfOptional().getNestedParameterType())) {
RequestParam requestParam = parameter.getParameterAnnotation(RequestParam.class);
return (requestParam != null &&
StringUtils.hasText(requestParam.name()));
}
else {
return true;
}
}
else {
if (parameter.hasParameterAnnotation(RequestPart.class)) {
return false;
}
parameter = parameter.nestedIfOptional();
if (MultipartResolutionDelegate.isMultipartArgument(parameter)) {
return true;
}
else if (this.useDefaultResolution) {
return BeanUtils.isSimpleProperty(parameter.getNestedParameterType());
}
else {
return false;
}
}
}
@Override
protected Object resolveName(
String name,
MethodParameter parameter,
NativeWebRequest request) throws Exception {
HttpServletRequest servletRequest =
request.getNativeRequest(HttpServletRequest.class);
if (servletRequest != null) {
Object mpArg = MultipartResolutionDelegate
.resolveMultipartArgument(name, parameter, servletRequest);
if (mpArg != MultipartResolutionDelegate.UNRESOLVABLE) {
return mpArg;
}
}
Object arg = null;
MultipartRequest multipartRequest =
request.getNativeRequest(MultipartRequest.class);
if (multipartRequest != null) {
List<MultipartFile> files = multipartRequest.getFiles(name);
if (!files.isEmpty()) {
arg = (files.size() == 1 ? files.get(0) : files);
}
}
if (arg == null) {
String[] paramValues = request.getParameterValues(name);
if (paramValues != null) {
arg = (paramValues.length == 1 ? paramValues[0] : paramValues);
}
}
return arg;
}
}返回值处理器的实现
HandlerMethodReturnValueHandler负责处理Controller方法的返回值:
public interface HandlerMethodReturnValueHandler {
boolean supportsReturnType(MethodParameter returnType);
void handleReturnValue(
Object returnValue,
MethodParameter returnType,
ModelAndViewContainer mavContainer,
NativeWebRequest webRequest) throws Exception;
}
// ResponseBody返回值处理器
public class RequestResponseBodyMethodProcessor
extends AbstractMessageConverterMethodProcessor {
@Override
public boolean supportsReturnType(MethodParameter returnType) {
return (AnnotatedElementUtils.hasAnnotation(
returnType.getContainingClass(), ResponseBody.class) ||
returnType.hasMethodAnnotation(ResponseBody.class));
}
@Override
public void handleReturnValue(
Object returnValue,
MethodParameter returnType,
ModelAndViewContainer mavContainer,
NativeWebRequest webRequest) throws IOException, HttpMediaTypeNotAcceptableException {
mavContainer.setRequestHandled(true);
ServletServerHttpRequest inputMessage = createInputMessage(webRequest);
ServletServerHttpResponse outputMessage = createOutputMessage(webRequest);
// 使用消息转换器写入响应
writeWithMessageConverters(returnValue, returnType, inputMessage, outputMessage);
}
protected <T> void writeWithMessageConverters(
T value,
MethodParameter returnType,
ServletServerHttpRequest inputMessage,
ServletServerHttpResponse outputMessage)
throws IOException, HttpMediaTypeNotAcceptableException {
Object body;
Class<?> valueType;
Type targetType;
if (value instanceof CharSequence) {
body = value.toString();
valueType = String.class;
targetType = String.class;
}
else {
body = value;
valueType = getReturnValueType(body, returnType);
targetType = GenericTypeResolver.resolveType(
getGenericType(returnType), returnType.getContainingClass());
}
// 选择合适的MediaType
MediaType selectedMediaType = null;
MediaType contentType = outputMessage.getHeaders().getContentType();
boolean isContentTypePreset = contentType != null && contentType.isConcrete();
if (isContentTypePreset) {
selectedMediaType = contentType;
}
else {
HttpServletRequest request = inputMessage.getServletRequest();
List<MediaType> acceptableTypes = getAcceptableMediaTypes(request);
List<MediaType> producibleTypes = getProducibleMediaTypes(
request, valueType, targetType);
List<MediaType> mediaTypesToUse = new ArrayList<>();
for (MediaType requestedType : acceptableTypes) {
for (MediaType producibleType : producibleTypes) {
if (requestedType.isCompatibleWith(producibleType)) {
mediaTypesToUse.add(
getMostSpecificMediaType(requestedType, producibleType));
}
}
}
MediaType.sortBySpecificityAndQuality(mediaTypesToUse);
for (MediaType mediaType : mediaTypesToUse) {
if (mediaType.isConcrete()) {
selectedMediaType = mediaType;
break;
}
}
}
// 使用选定的转换器进行转换
if (selectedMediaType != null) {
for (HttpMessageConverter<?> converter : this.messageConverters) {
GenericHttpMessageConverter genericConverter =
(converter instanceof GenericHttpMessageConverter ?
(GenericHttpMessageConverter<?>) converter : null);
if (genericConverter != null ?
((GenericHttpMessageConverter) converter).canWrite(
targetType, valueType, selectedMediaType) :
converter.canWrite(valueType, selectedMediaType)) {
body = getAdvice().beforeBodyWrite(body, returnType,
selectedMediaType, converter.getClass(),
inputMessage, outputMessage);
if (body != null) {
if (genericConverter != null) {
genericConverter.write(body, targetType,
selectedMediaType, outputMessage);
}
else {
((HttpMessageConverter) converter).write(
body, selectedMediaType, outputMessage);
}
}
return;
}
}
}
}
}拦截器链的执行机制
public class HandlerExecutionChain {
private final Object handler;
private final List<HandlerInterceptor> interceptorList = new ArrayList<>();
private int interceptorIndex = -1;
boolean applyPreHandle(
HttpServletRequest request,
HttpServletResponse response) throws Exception {
for (int i = 0; i < this.interceptorList.size(); i++) {
HandlerInterceptor interceptor = this.interceptorList.get(i);
if (!interceptor.preHandle(request, response, this.handler)) {
triggerAfterCompletion(request, response, null);
return false;
}
this.interceptorIndex = i;
}
return true;
}
void applyPostHandle(
HttpServletRequest request,
HttpServletResponse response,
ModelAndView mv) throws Exception {
for (int i = this.interceptorList.size() - 1; i >= 0; i--) {
HandlerInterceptor interceptor = this.interceptorList.get(i);
interceptor.postHandle(request, response, this.handler, mv);
}
}
void triggerAfterCompletion(
HttpServletRequest request,
HttpServletResponse response,
Exception ex) {
for (int i = this.interceptorIndex; i >= 0; i--) {
HandlerInterceptor interceptor = this.interceptorList.get(i);
try {
interceptor.afterCompletion(
request, response, this.handler, ex);
}
catch (Throwable ex2) {
logger.error("HandlerInterceptor.afterCompletion threw exception", ex2);
}
}
}
}性能优化建议
1. 合理使用@RestController
@RestController // 相当于@Controller + @ResponseBody
@RequestMapping("/api/v1")
public class UserApiController {
@GetMapping("/users/{id}")
public ResponseEntity<User> getUser(@PathVariable Long id) {
// 直接返回JSON,无需视图解析
return ResponseEntity.ok(userService.findById(id));
}
}2. 启用异步处理
@RestController
public class AsyncController {
@GetMapping("/async/callable")
public Callable<String> processCallable() {
return () -> {
// 在独立线程中执行耗时操作
Thread.sleep(2000);
return "Async result";
};
}
@GetMapping("/async/deferred")
public DeferredResult<String> processDeferredResult() {
DeferredResult<String> result = new DeferredResult<>(5000L);
// 异步设置结果
CompletableFuture.runAsync(() -> {
try {
Thread.sleep(1000);
result.setResult("Deferred result");
} catch (InterruptedException e) {
result.setErrorResult(e);
}
});
return result;
}
}3. 自定义参数解析器
@Component
public class CurrentUserArgumentResolver
implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.getParameterType().equals(User.class) &&
parameter.hasParameterAnnotation(CurrentUser.class);
}
@Override
public Object resolveArgument(
MethodParameter parameter,
ModelAndViewContainer mavContainer,
NativeWebRequest webRequest,
WebDataBinderFactory binderFactory) {
HttpServletRequest request =
webRequest.getNativeRequest(HttpServletRequest.class);
// 从请求中获取当前用户信息
String token = request.getHeader("Authorization");
return userService.getUserByToken(token);
}
}
// 配置自定义参数解析器
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Autowired
private CurrentUserArgumentResolver currentUserArgumentResolver;
@Override
public void addArgumentResolvers(
List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(currentUserArgumentResolver);
}
}在TRAE IDE中的实践应用
在使用TRAE IDE开发Spring应用时,其智能代码补全功能能够自动识别Controller注解的上下文,提供精准的代码建议。当你输入@Controller或@RestController时,TRAE会自动提示相关的请求映射注解,并根据方法签名智能推荐合适的参数注解。
TRAE的代码索引功能可以快速定位项目中所有的Controller类,通过#Workspace功能,你可以让AI助手分析整个项目的Controller结构,识别潜在的性能瓶颈或设计问题。
总结
Spring Controller注解的底层实现涉及组件扫描、Bean定义注册、请求映射、参数解析、返回值处理等多个核心环节。理解这些机制不仅有助于编写更高效的代码,还能在遇到问题时快速定位和解决。
通过深入分析源码,我们可以看到Spring框架的设计精髓:通过抽象和分层,将复杂的Web请求处理流程分解为多个可扩展的组件,每个组件都遵循 单一职责原则,共同构建了一个强大而灵活的Web框架。
(此内容由 AI 辅助生成,仅供参考)