docs/Spring全家桶/SpringMVC源码分析/Spring容器启动Tomcat.md
'' spring mvc ֮ springmvc demo @EnableWebMvc עһУṩһʾ demo demo servlet Ȼͨ servlet3.0 淶 DispatcherServlet עᵽ servlet УȻ DispatcherServlet#init spring ̾
ûʲô⣬Ҳãֻ spring ȡ DispatcherServlet
@Component
public class Test {
// ǰṩʾtomcatspringע벻˵
@Autowired
public DispatcherServlet dispatcherServlet;
...
}
ʱspring ϶ᱨΪҲ DispatcherServlet Ӧ bean
ڿ springboot Դʱ spring tomcat ģ෴springboot spring Ȼ spring tomcat أﱾṩһ demo ģ¡
DispatcherServlet@Component
@EnableWebMvc
public class MvcConfig implements WebMvcConfigurer {
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/views/");
viewResolver.setSuffix(".html");
registry.viewResolver(viewResolver);
}
/**
* dispatcherServlet
* @param webApplicationContext
* @return
*/
@Bean
public DispatcherServlet dispatcherServlet(WebApplicationContext webApplicationContext) {
return new DispatcherServlet(webApplicationContext);
}
}
Ը˵£
MvcConfig ౻ @EnableWebMvc עǣʾҪ web mvcMvcConfig ʵ WebMvcConfigurerͨд WebMvcConfigurer ķʵԶ web mvcMvcConfig л DispatcherServlet bean bean ᱣ浽 springWebApplicationInitializer ʵ@Component
public class MyWebApplicationInitializer implements WebApplicationInitializer {
private static BeanFactory beanFactory;
private static AbstractRefreshableWebApplicationContext applicationContext;
@Override
public void onStartup(ServletContext servletContext) {
// beanFactory лȡ DispatcherServlet עᵽservlet
DispatcherServlet servlet = beanFactory.getBean(DispatcherServlet.class);
ServletRegistration.Dynamic registration = servletContext.addServlet("app", servlet);
// loadOnStartup ó -1 ʱֻڵһʱŻ init
registration.setLoadOnStartup(-1);
registration.addMapping("/*");
// Ϊ applicationContext servletContext
applicationContext.setServletContext(servletContext);
}
/**
* beanFactory
* ΪʲôҪ beanFactoryֵΪ DispatcherServlet Ҫ beanFactory лȡ
* @param beanFactory
* @throws BeansException
*/
public static void setBeanFactory(BeanFactory beanFactory) throws BeansException {
MyWebApplicationInitializer.beanFactory = beanFactory;
}
/**
* applicationContext
* ΪʲôҪ applicationContext ֵΪ servletContext Ҫõ applicationContext
* @param applicationContext
*/
public static void setApplicationContext(
AbstractRefreshableWebApplicationContext applicationContext) {
MyWebApplicationInitializer.applicationContext = applicationContext;
}
}
WebApplicationInitializer spring servlet 3.0 淶ʵ֣ spring mvc ֮ springmvc demo @EnableWebMvc עһҲϸtomcat ʱִ WebApplicationInitializer#onStartup
MyWebApplicationInitializer ˵£
MyWebApplicationInitializer ̬ԱbeanFactory applicationContextӦṩ̬ set Ҫעǣ̬ set Ҫ onStartup() ǰãҲ tomcat ǰõãMyWebApplicationInitializer#onStartup УǴ beanFactory лȡ DispatcherServletȻעᵽ servlet УȻ onStartup(...) IJ servletContext õ applicationContextServletContextAwareProcessorpublic class MyServletContextAwareProcessor extends ServletContextAwareProcessor {
AbstractRefreshableWebApplicationContext webApplicationContext;
/**
* webApplicationContext
* @param webApplicationContext
*/
public MyServletContextAwareProcessor(
AbstractRefreshableWebApplicationContext webApplicationContext) {
this.webApplicationContext = webApplicationContext;
}
/**
* ServletContext
* ȴ webApplicationContext лȡȡٴӸлȡ
* @return
*/
@Override
protected ServletContext getServletContext() {
ServletContext servletContext = this.webApplicationContext.getServletContext();
return (servletContext != null) ? servletContext : super.getServletContext();
}
@Override
protected ServletConfig getServletConfig() {
ServletConfig servletConfig = this.webApplicationContext.getServletConfig();
return (servletConfig != null) ? servletConfig : super.getServletConfig();
}
}
MyWebApplicationInitializer#onStartup ж applicationContext õ servletContext ʹõģMyServletContextAwareProcessor Ĺ췽 webApplicationContextȻд getServletContext() ȡ servletContext ʱȴ webApplicationContext лȡȡٴӸлȡ
ApplicationContext ʵApplicationContext Ҫѡֱչ AnnotationConfigWebApplicationContext
public class MyWebApplicationContext extends AnnotationConfigWebApplicationContext {
private Tomcat tomcat;
/**
* д postProcessBeanFactory
* Զ MyServletContextAwareProcessor
* @param beanFactory
*/
@Override
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
beanFactory.addBeanPostProcessor(new MyServletContextAwareProcessor(this));
beanFactory.ignoreDependencyInterface(ServletContextAware.class);
WebApplicationContextUtils.registerWebApplicationScopes(getBeanFactory());
}
/**
* tomcat
*/
@Override
protected void onRefresh() {
// ȵøķ
super.onRefresh();
// MyWebApplicationInitializer beanFactory applicationContext
MyWebApplicationInitializer.setBeanFactory(getBeanFactory());
MyWebApplicationInitializer.setApplicationContext(this);
// tomcatĴ
tomcat = new Tomcat();
Connector connector = new Connector();
connector.setPort(8080);
connector.setURIEncoding("UTF-8");
tomcat.getService().addConnector(connector);
Context context = tomcat.addContext("", System.getProperty("java.io.tmpdir"));
LifecycleListener lifecycleListener = null;
try {
lifecycleListener = (LifecycleListener)
Class.forName(tomcat.getHost().getConfigClass())
.getDeclaredConstructor().newInstance();
context.addLifecycleListener(lifecycleListener);
// tomcat
tomcat.start();
} catch (Exception e) {
System.out.println("쳣");
e.printStackTrace();
}
}
}
չ spring ̣һдһһ:
postProcessBeanFactory()ҪΪע MyServletContextAwareProcessorǰ MyServletContextAwareProcessor עģ֮дΪʹ tomcat ṩ ServletContextonRefresh() MyWebApplicationInitializer beanFactory applicationContext ֵȻ tomcatControllerһ ControllerҪǰ֤ĿǷ
@RestController
@RequestMapping("/test")
public class TestController {
@RequestMapping("/hello")
public String hello() {
System.out.println("hello!!!");
return "hello world!";
}
}
ˣҪǴ spring Ҳ൱
@ComponentScan
public class MvcDemo03Main {
public static void main(String[] args) throws Exception {
MyWebApplicationContext webApplicationContext = new MyWebApplicationContext();
webApplicationContext.register(MvcDemo03Main.class);
webApplicationContext.refresh();
}
}
У http://localhost:8080/test/hello£
ҳ棺
̨
DispatcherServlet#init ٴ springǰǷʹ tomcat spring ķʽʱspring DispatcherServlet#init ģʹ spring tomcat ʽʱtomcat ִ DispatcherServlet#init ʱٴ spring
ֱӽ FrameworkServlet#initWebApplicationContext ϶ϵ㣺
wac this.webApplicationContext MyWebApplicationContext ʵڴ DispatcherServlet ʱ:
@Bean
public DispatcherServlet dispatcherServlet(WebApplicationContext webApplicationContext) {
// ڹ췽IJд webApplicationContext
return new DispatcherServlet(webApplicationContext);
}
ΪʲôΪ DispatcherServlet#init úﴦ spring ģϵе if (!cwac.isActive()) {... ʱ!cwac.isActive() ؽΪ false if spring Ͳִеˡ
ͨ spring tomcat DispatcherServlet#init ﲻٴ spring DispatcherServlet һ spring beanǾͿڴʹ @Autowired ע⽫ע뵽ˣ
@Component
public class Test {
// ĵʾ spring tomcatǿעɹ
@Autowired
public DispatcherServlet dispatcherServlet;
...
}
spring tomcat ķ͵еѵ**ν tomcat ṩ ServletContext õ ServletContextAwareProcessor **еĽʽעᡣ
ԭӣhttps://my.oschina.net/funcy/blog/4928222 ߸ˮƽд֮ӭָԭףҵתϵȨҵתע