- mvc的自动装配
在SpringFramework时代mvc就可以进行自动装配了,
但前提是servlet依赖是3.0+
servlet SPI:ServletContainerInitializer
当servlet容器启动的时候,ServletContainerInitializer中的onStartup方法会被回调,
ServletContext中可动态装载监听器或过滤器或其他组件,那么spring也借助这个接口,实现了自己的东西。
spring的适配:SpringServletContainerInitializer
图中@HandlesTypes为筛选器,在servlet启动时,servlet的jar包会引入许多jar包,@HandlesTypes用来筛选哪些是需要装载的。
Spring SPI:WebApplicationInitializer
进去看这个接口:
从注释可看出有三个实现类
编程实现:AbstractDispatcherServletInitializer
从上图源码注释可以看出,AbstractDispatcherServletInitializer属于WebApplicationInitializer的一个实现类,源码:
/**
* Register a {@link DispatcherServlet} against the given servlet context.
* <p>This method will create a {@code DispatcherServlet} with the name returned by
* {@link #getServletName()}, initializing it with the application context returned
* from {@link #createServletApplicationContext()}, and mapping it to the patterns
* returned from {@link #getServletMappings()}.
* <p>Further customization can be achieved by overriding {@link
* #customizeRegistration(ServletRegistration.Dynamic)} or
* {@link #createDispatcherServlet(WebApplicationContext)}.
* @param servletContext the context to register the servlet against
*/
protected void registerDispatcherServlet(ServletContext servletContext) {
String servletName = getServletName();
Assert.hasLength(servletName, "getServletName() must not return null or empty");
WebApplicationContext servletAppContext = createServletApplicationContext();
Assert.notNull(servletAppContext, "createServletApplicationContext() must not return null");
FrameworkServlet dispatcherServlet = createDispatcherServlet(servletAppContext);
Assert.notNull(dispatcherServlet, "createDispatcherServlet(WebApplicationContext) must not return null");
dispatcherServlet.setContextInitializers(getServletApplicationContextInitializers());
ServletRegistration.Dynamic registration = servletContext.addServlet(servletName, dispatcherServlet);
if (registration == null) {
throw new IllegalStateException("Failed to register servlet with name '" + servletName + "'. " +
"Check if there is another servlet registered under the same name.");
}
registration.setLoadOnStartup(1);
registration.addMapping(getServletMappings());
registration.setAsyncSupported(isAsyncSupported());
Filter[] filters = getServletFilters();
if (!ObjectUtils.isEmpty(filters)) {
for (Filter filter : filters) {
registerServletFilter(servletContext, filter);
}
}
customizeRegistration(registration);
}
onstartup会调registerDispatcherServlet这个方法。
这个方式的实现过程不再写了,为什么不写呢?因为下面的注解实现AbstractAnnotationConfigDispatcherServletInitializer通过源码可知,他继承AbstractDispatcherServletInitializer,所以具体详情看AbstractAnnotationConfigDispatcherServletInitializer源码即可。
注解实现:AbstractAnnotationConfigDispatcherServletInitializer
实现:
web.xml中全部注释
<web-app>
<!--<servlet>使用可执行 Tomcat Maven 插件
Spring Framework 时代的重新认识
Web MVC 核心组件
<servlet-name>app</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/app-context.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>app</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>-->
</web-app>
新建配置类:
/**
* {@link DispatcherServlet} 配置类
*/
@ComponentScan(basePackages = "com.haozi.web")
public class DispatcherServletConfiguration {
}
public class DefaultAnnotationConfigDispatcherServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() { //对应web.xml中的init-param
return new Class[0];
}
@Override
protected Class<?>[] getServletConfigClasses() { //DispatcherServlet
return new Class[]{DispatcherServletConfiguration.class};
}
@Override
protected String[] getServletMappings() { //映射
return new String[]{"/"};
}
}
其实这种实现方式就是把xml的替换成编码的方式。