Back to Javatutorial

Spring容器启动Tomcat

docs/Spring全家桶/SpringMVC源码分析/Spring容器启动Tomcat.md

1.0.09.0 KB
Original Source

'' spring mvc ֮ springmvc demo @EnableWebMvc עһУṩһʾ demo demo servlet Ȼͨ servlet3.0DispatcherServlet עᵽ 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 ģ¡

1. ׼ 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 mvc
  • MvcConfig ʵ WebMvcConfigurerͨд WebMvcConfigurer ķʵԶ web mvc
  • MvcConfig л DispatcherServlet bean bean ᱣ浽 spring

2. ׼һ WebApplicationInitializer ʵ

@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 õ applicationContext

3. ׼һ ServletContextAwareProcessor

public 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 лȡȡٴӸ෽лȡ

4. ׼һ 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 עģ֮дΪʹ tomcatServletContext
  • onRefresh()MyWebApplicationInitializer beanFactory applicationContext ֵȻ tomcat

5. ׼һ򵥵 Controller

׼һ ControllerҪǰ֤ĿǷ

@RestController
@RequestMapping("/test")
public class TestController {

    @RequestMapping("/hello")
    public String hello() {
        System.out.println("hello!!!");
        return "hello world!";
    }

}

6.

ˣҪǴ 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£

ҳ棺

̨

7. ⣺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 ķ͵еѵ**ν tomcatServletContext õ ServletContextAwareProcessor **еĽʽעᡣ


ԭӣhttps://my.oschina.net/funcy/blog/4928222 ߸ˮƽд֮ӭָԭףҵתϵ߻Ȩҵתע