SpringBoot扩展点之三:SpringBootServletInitializer扩展

SpringBootServletInitializer

熟悉了SpringApplication的原理之后,我们再来了解SpringBootServletInitializer的原理就比较容易了。

public class ServletInitializer extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(DemoWarApplication.class);
    }
}

SpringBootServletInitializer就是一个org.springframework.web.context.WebApplicationContext,容器启动时会调用其onStartup(ServletContext servletContext)方法,接下来我么就来看一下这个方法:

public void onStartup(ServletContext servletContext) throws ServletException {
        this.logger = LogFactory.getLog(this.getClass());
        final WebApplicationContext rootAppContext = this.createRootApplicationContext(servletContext);
        if(rootAppContext != null) {
            servletContext.addListener(new ContextLoaderListener(rootAppContext) {
                public void contextInitialized(ServletContextEvent event) {
                }
            });
        } else {
            this.logger.debug("No ContextLoaderListener registered, as createRootApplicationContext() did not return an application context");
        }

    }

这里的核心方法就是createRootApplicationContext(servletContext):

protected WebApplicationContext createRootApplicationContext(ServletContext servletContext) {

        //创建SpringApplicationBuilder,并用其生产出SpringApplication对象
        SpringApplicationBuilder builder = this.createSpringApplicationBuilder();
        builder.main(this.getClass());

        ApplicationContext parent = this.getExistingRootWebApplicationContext(servletContext);
        if(parent != null) {
            this.logger.info("Root context already created (using as parent).");
            servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, (Object)null);
            builder.initializers(new ApplicationContextInitializer[]{new ParentContextApplicationContextInitializer(parent)});
        }

        //初始化并封装SpringApplicationBuilder对象,为SpringApplication对象增加ApplicationContextInitializer和ApplicationListener做准备
        builder.initializers(new ApplicationContextInitializer[]{new ServletContextApplicationContextInitializer(servletContext)});
        builder.listeners(new ApplicationListener[]{new ServletContextApplicationListener(servletContext)});
        //指定创建的ApplicationContext类型
        builder.contextClass(AnnotationConfigEmbeddedWebApplicationContext.class);

        //传递入口类,并构建SpringApplication对象
        //可以通过configure()方法对SpringBootServletInitializer进行扩展
        builder = this.configure(builder);
        SpringApplication application = builder.build();

        if(application.getSources().isEmpty() && AnnotationUtils.findAnnotation(this.getClass(), Configuration.class) != null) {
            application.getSources().add(this.getClass());
        }

        Assert.state(!application.getSources().isEmpty(), "No SpringApplication sources have been defined. Either override the configure method or add an @Configuration annotation");
        if(this.registerErrorPageFilter) {
            application.getSources().add(ErrorPageFilter.class);
        }

        //最后调用SpringApplication的run方法
        return this.run(application);
    }

说明
SpringBootServletInitializer的执行过程,简单来说就是通过SpringApplicationBuilder构建并封装SpringApplication对象,并最终调用SpringApplication的run方法的过程。


扩展SpringBootServletInitializer

与扩展SpringApplication类似,ApplicationContextInitializerApplicationListener可以基于SpringApplicationBuilder提供的public方法进行扩展

public class ServletInitializer extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        application.initializers(MyApplicationContextInitializer1,MyApplicationContextInitializer2);
        application.listeners(MyApplicationListener1,MyApplicationListener2)
        return application.sources(DemoWarApplication.class);
    }

}

 

posted on 2019-07-24 16:35  duanxz  阅读(6954)  评论(0编辑  收藏  举报