Spring 容器如何引用我们作为参数传递给方法的接口或 class 类型
How does Spring container gives reference to interface or class type we pass as an arguments to method
我一直在研究spring和spring mvc框架,我很想知道spring容器是如何给我们引用任何接口或Class 类型我们作为参数传递给我们的方法。
例如,当我们在 Web 应用程序中创建一个 Servlet 时,它会扩展 HttpServlet,因此当我们覆盖 doGet 或 doPost 方法时,Web 容器实例化 Servlet 并将对 HttpServletRequest 和 HttpServletResponse 对象的引用传递给 doGet 或 doPost 方法:
public class DemoServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//container gives reference to request and response object
}
}
我想到的问题是 spring 容器如何知道它需要实例化什么对象引用,即它如何扫描方法,因为我们的 class 不会覆盖任何 Class 或接口方法,以便它可以知道它需要提供对该对象的引用。由于这些 class 或接口类型未在应用程序上下文文件中声明为 beans。例如:
@Controller
@RequestMapping("/")
public class ContactController {
@RequestMapping(value="savecontact", method=RequestMethod.POST)
public String saveContact(@ModelAttribute("contact") Contact contact, BindingResult errors, HttpServletRequest request, HttpServletResponse response) {
...
}
}
Spring 如何提供对 BindingResult、HttpServletRequest、HttpServletResponse 对象和任何其他 Spring 或 Servlet class 或我们作为参数传递给方法的接口类型的引用?它是否具有在应用程序启动时实例化的默认对象列表或是否扫描方法?
当您使用 @RequestMapping
注释控制器方法时,该方法的参数将成为参数解析过程的主题。接口 HandlerMethodArgumentResolver
及其实现是该机制的核心。该接口持有两个方法supports
和resolveArguments
简单来说,所有列出的参数都通过使用 RequestMappingHandlerAdapter
注册的默认解析器列表传递(检查 getDefaultArgumentResolvers
方法),如果解析器支持该类型,则 resolveArgument
方法被调用并注入一个实例作为参数。
对于您声明的四种类型,相应的解析器是
ServletModelAttributeMethodProcessor
ErrorsMethodArgumentResolver
ServletRequestMethodArgumentResolver
ServletResponseMethodArgumentResolver
默认全部注册
基于参数解析机制,添加一个 custom resolver 也很容易,它也将实例化并注入任何自定义类型
作为Master Slave回答的后续...about @ModelAttribute arguments
An @ModelAttribute on a method argument indicates the argument should be retrieved from the model. If not present in the model,
the argument should be instantiated first and then added to the model.
Once present in the model, the argument’s fields should be
populated from all request parameters that have matching names. This
is known as data binding in Spring MVC
"where" does spring find a @ModelAttribute method arg:
- It may already be in the model
- due to use of @SessionAttributes
- due to an @ModelAttribute method in the same controller
- It may be retrieved based on a URI template variable and type converter (explained in more detail below).
- It may be instantiated using its default constructor.
我一直在研究spring和spring mvc框架,我很想知道spring容器是如何给我们引用任何接口或Class 类型我们作为参数传递给我们的方法。
例如,当我们在 Web 应用程序中创建一个 Servlet 时,它会扩展 HttpServlet,因此当我们覆盖 doGet 或 doPost 方法时,Web 容器实例化 Servlet 并将对 HttpServletRequest 和 HttpServletResponse 对象的引用传递给 doGet 或 doPost 方法:
public class DemoServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//container gives reference to request and response object
}
}
我想到的问题是 spring 容器如何知道它需要实例化什么对象引用,即它如何扫描方法,因为我们的 class 不会覆盖任何 Class 或接口方法,以便它可以知道它需要提供对该对象的引用。由于这些 class 或接口类型未在应用程序上下文文件中声明为 beans。例如:
@Controller
@RequestMapping("/")
public class ContactController {
@RequestMapping(value="savecontact", method=RequestMethod.POST)
public String saveContact(@ModelAttribute("contact") Contact contact, BindingResult errors, HttpServletRequest request, HttpServletResponse response) {
...
}
}
Spring 如何提供对 BindingResult、HttpServletRequest、HttpServletResponse 对象和任何其他 Spring 或 Servlet class 或我们作为参数传递给方法的接口类型的引用?它是否具有在应用程序启动时实例化的默认对象列表或是否扫描方法?
当您使用 @RequestMapping
注释控制器方法时,该方法的参数将成为参数解析过程的主题。接口 HandlerMethodArgumentResolver
及其实现是该机制的核心。该接口持有两个方法supports
和resolveArguments
简单来说,所有列出的参数都通过使用 RequestMappingHandlerAdapter
注册的默认解析器列表传递(检查 getDefaultArgumentResolvers
方法),如果解析器支持该类型,则 resolveArgument
方法被调用并注入一个实例作为参数。
对于您声明的四种类型,相应的解析器是
ServletModelAttributeMethodProcessor
ErrorsMethodArgumentResolver
ServletRequestMethodArgumentResolver
ServletResponseMethodArgumentResolver
默认全部注册
基于参数解析机制,添加一个 custom resolver 也很容易,它也将实例化并注入任何自定义类型
作为Master Slave回答的后续...about @ModelAttribute arguments
An @ModelAttribute on a method argument indicates the argument should be retrieved from the model. If not present in the model, the argument should be instantiated first and then added to the model. Once present in the model, the argument’s fields should be populated from all request parameters that have matching names. This
is known as data binding in Spring MVC"where" does spring find a @ModelAttribute method arg:
- It may already be in the model
- due to use of @SessionAttributes
- due to an @ModelAttribute method in the same controller
- It may be retrieved based on a URI template variable and type converter (explained in more detail below).
- It may be instantiated using its default constructor.