欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringBoot實(shí)現(xiàn)嵌入式 Servlet容器

 更新時(shí)間:2023年12月06日 10:31:48   作者:程序猿進(jìn)階  
傳統(tǒng)的Spring MVC工程部署時(shí)需要將WAR文件放置在servlet容器的文檔目錄內(nèi),而Spring Boot工程使用嵌入式servlet容器省去了這一步驟,本文就來(lái)設(shè)置一下相關(guān)配置,感興趣的可以了解一下

一、如何定制和修改Servlet容器的相關(guān)配置

前言: SpringBootWeb環(huán)境下,默認(rèn)使用的是Tomact作為嵌入式的Servlet容器;

在這里插入圖片描述

【1】修改和server相關(guān)的配置(ServerProperties實(shí)現(xiàn)了EmbeddedServletContainerCustomizer)例如:修改端口號(hào)

#通用的Servlet容器設(shè)置:修改端口號(hào)
server:
  port: 8081
  tomcat:  #設(shè)置Tomact的相關(guān)屬性,例如編碼格式
    uri-encoding: utf-8

? 我們也可以進(jìn)入port所屬的對(duì)象中,發(fā)現(xiàn)其他可修改的參數(shù)等等,如下:

@ConfigurationProperties(
    prefix = "server",
    ignoreUnknownFields = true
)
public class ServerProperties implements EmbeddedServletContainerCustomizer, EnvironmentAware, Ordered {
    private Integer port;
    private InetAddress address;
    private String contextPath;
    private String displayName = "application";
    ......

【2】編寫(xiě)一個(gè)EmbeddedServletContainerCustomizer:嵌入式的 Servlet容器的定制器,來(lái)修改 Servlet容器的配置。其實(shí)1中的 ServerProperties也是實(shí)現(xiàn)了 EmbeddedServletContainerCustomizer。xxxCustomizer 幫組我們進(jìn)行定制配置。

@Configuration
public class MyMvcConfig extends WebMvcConfigurerAdapter {
    @Bean
    public EmbeddedServletContainerCustomizer embeddedServletContainerCustomizer(){
        return new EmbeddedServletContainerCustomizer() {
            @Override
            public void customize(ConfigurableEmbeddedServletContainer container) {
                container.setPort(8082);
            }
        };
    }

二、注冊(cè)Servlet三大組件【Servlet、Filter、Listener】

由于SpringBoot默認(rèn)是以 jar包的方式啟動(dòng)嵌入的Servlet容器來(lái)啟動(dòng)SpringBootweb應(yīng)用,沒(méi)有web.xml文件。注冊(cè)三大組件的方式如下:

【1】通過(guò) ServletRegistrationBean注冊(cè)自定義的Servlet。

//首先創(chuàng)建一個(gè)Servlet
public class MyServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doGet(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().write("Hello MyServlet");
        super.doPost(req, resp);
    }
}

//將創(chuàng)建的Servlet通過(guò)配置類(lèi)注入到容器中,兩個(gè)是不同的類(lèi)。
@Configuration
public class MyMvcConfig extends WebMvcConfigurerAdapter {
    @Bean
    public ServletRegistrationBean myServlet(){
        ServletRegistrationBean registrationBean = new ServletRegistrationBean(new MyServlet(), "/myServlet");
        return registrationBean;
    }

【2】通過(guò) FilterRegistrationBean 注冊(cè)攔截器 Filter。

//自定義一個(gè)filter實(shí)現(xiàn)servlet.Filter接口
public class myFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.printf("myFilter");
        filterChain.doFilter(servletRequest,servletResponse);
    }

    @Override
    public void destroy() {

    }
}

//通過(guò)配置類(lèi)注入自定義的Filter
@Configuration
public class MyMvcConfig extends WebMvcConfigurerAdapter {
    @Bean
    public FilterRegistrationBean myFilter(){
        FilterRegistrationBean registrationBean = new FilterRegistrationBean();
        registrationBean.setFilter(new myFilter());
        registrationBean.setUrlPatterns(Arrays.asList("/hello","/myFilter"));
        return registrationBean;
    }
【3】通過(guò)`ServletListenerRegistrationBean`注冊(cè)自定義的`Listener`。
```java
//創(chuàng)建自定義的Listener監(jiān)聽(tīng)
public class myListener implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        System.out.printf("服務(wù)啟動(dòng)");
    }

    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
        System.out.printf("服務(wù)銷(xiāo)毀");
    }
}

//通過(guò)配置類(lèi)注入自定義的listener
@Configuration
public class MyMvcConfig extends WebMvcConfigurerAdapter {

    public ServletListenerRegistrationBean myListener(){
        ServletListenerRegistrationBean<MyListener> servletListenerRegistrationBean = new ServletListenerRegistrationBean<>(new MyListener());
        return servletListenerRegistrationBean;
    }

三、使用其他 Servlet容器:Jetty(長(zhǎng)連接引用)、Undertow(不支持JSP)

【1】我們?cè)诙ㄖ魄度胧降?code>Servlet容器時(shí),會(huì)傳入ConfigurableEmbeddedServletContainer類(lèi),我們通過(guò)Ctrl+T查看此可配置嵌入式類(lèi)容器中可以配置Tomcat、JettyUndertow。

//ConfigurableEmbeddedServletContainer 
@Bean
public EmbeddedServletContainerCustomizer embeddedServletContainerCustomizer(){
    return new EmbeddedServletContainerCustomizer() {
        @Override
        public void customize(ConfigurableEmbeddedServletContainer container) {
            container.setPort(8082);
        }
    };
}

【2】默認(rèn)使用Tomcat,因?yàn)?code>starter-web引入的是Tomcatstarter。我們排除Tomcat的依賴,引入Jetty的依賴即可。

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-web</artifactId>
	<exclusions>
		<exclusion>
			<artifactId>spring-boot-starter-tomcat</artifactId>
			<groupId>org.springframework.boot</groupId>
		</exclusion>
	</exclusions>
</dependency>

<dependency>
	<artifactId>spring-boot-starter-Jetty</artifactId>
	<groupId>org.springframework.boot</groupId>
</dependency>

四、嵌入式 Servlet容器自動(dòng)配置原理

【1】EmbeddedServletContainerAutoConfiguration類(lèi)主要用來(lái)自動(dòng)配置嵌入式的Servlet容器。

@AutoConfigureOrder(-2147483648)
@Configuration
@ConditionalOnWebApplication
 //導(dǎo)入BeanPostProcessorsRegistrar:后置處理器:在bean初始化前后,執(zhí)行(剛創(chuàng)建完對(duì)象,還沒(méi)屬性賦值)初始化工作.
 //給容器中導(dǎo)入一些組件,導(dǎo)入了embeddedServletContainerCustomizerBeanPostProcessor
@Import({EmbeddedServletContainerAutoConfiguration.BeanPostProcessorsRegistrar.class})
public class EmbeddedServletContainerAutoConfiguration {
    @Configuration
    @ConditionalOnClass({Servlet.class, Tomcat.class})//判斷當(dāng)前Servlet中是否引入的Tomcat依賴
    @ConditionalOnMissingBean(
        value = {EmbeddedServletContainerFactory.class},
        search = SearchStrategy.CURRENT
    )//判斷當(dāng)前容器中,沒(méi)有用戶自定義的EmbeddedServletContainerFactory嵌入式的Servlet容器工廠,
    //作用:創(chuàng)建嵌入式的servlet容器。
    public static class EmbeddedTomcat {
        public EmbeddedTomcat() {
        }

        @Bean
        public TomcatEmbeddedServletContainerFactory tomcatEmbeddedServletContainerFactory() {
            return new TomcatEmbeddedServletContainerFactory();
        }
    }

    @Configuration
    @ConditionalOnClass({Servlet.class, Undertow.class, SslClientAuthMode.class})
    @ConditionalOnMissingBean(
        value = {EmbeddedServletContainerFactory.class},
        search = SearchStrategy.CURRENT
    )
    public static class EmbeddedUndertow {
        public EmbeddedUndertow() {
        }

        @Bean
        public UndertowEmbeddedServletContainerFactory undertowEmbeddedServletContainerFactory() {
            return new UndertowEmbeddedServletContainerFactory();
        }
    }

    @Configuration
    @ConditionalOnClass({Servlet.class, Server.class, Loader.class, WebAppContext.class})
    @ConditionalOnMissingBean(
        value = {EmbeddedServletContainerFactory.class},
        search = SearchStrategy.CURRENT
    )
    public static class EmbeddedJetty {
        public EmbeddedJetty() {
        }

        @Bean
        public JettyEmbeddedServletContainerFactory jettyEmbeddedServletContainerFactory() {
            return new JettyEmbeddedServletContainerFactory();
        }
    }
}

【2】嵌入式的容器工廠:EmbeddedServletContainerFactory,用來(lái)創(chuàng)建嵌入式的Servlet容器。

public interface EmbeddedServletContainerFactory {
     //獲取嵌入式的Servlet容器
     EmbeddedServletContainer getEmbeddedServletContainer(ServletContextInitializer... var1); 
}

? SpringBoot 再帶了三種嵌入式的容器工廠,如下:

【3】EmbeddedServletContainer:嵌入式的容器,SpringBoot 為我們提供了三種不同的嵌入式容器,與工廠相互對(duì)應(yīng),如下:

【4】我們進(jìn)入工廠類(lèi) TomcatEmbeddedServletContainerFactory發(fā)現(xiàn),其實(shí)也是創(chuàng)建一個(gè) Tomcat并配置其基本屬性。

public EmbeddedServletContainer getEmbeddedServletContainer(ServletContextInitializer... initializers) {
	//創(chuàng)建Tomcat
	Tomcat tomcat = new Tomcat();

	//配置Tomcat的基本環(huán)境
	File baseDir = this.baseDirectory != null?this.baseDirectory:this.createTempDir("tomcat");
	tomcat.setBaseDir(baseDir.getAbsolutePath());
	Connector connector = new Connector(this.protocol);
	tomcat.getService().addConnector(connector);
	this.customizeConnector(connector);
	tomcat.setConnector(connector);
	tomcat.getHost().setAutoDeploy(false);
	this.configureEngine(tomcat.getEngine());
	Iterator var5 = this.additionalTomcatConnectors.iterator();

	while(var5.hasNext()) {
		Connector additionalConnector = (Connector)var5.next();
		tomcat.getService().addConnector(additionalConnector);
	}

	this.prepareContext(tomcat.getHost(), initializers);
	//將配置好的Tomcat傳入,并啟動(dòng)Tomcat,Tomcat.start()
	return this.getTomcatEmbeddedServletContainer(tomcat);
}

【5】用戶自定義的Servlet容器配置類(lèi)和SpringBoot默認(rèn)的ServerProperties配置類(lèi),都實(shí)現(xiàn)了EmbeddedServletContainerCustomizer接口。到底是怎么實(shí)現(xiàn)的哪?其實(shí)是SpringBoot自動(dòng)配置類(lèi)中引入了后置處理器,如下:

//與用戶自定義的Servlet容器實(shí)現(xiàn)的接口名很類(lèi)似,有一定的命名規(guī)則。
embeddedServletContainerCustomizerBeanPostProcessor

? 進(jìn)入后置處理器類(lèi)中,重點(diǎn)看如下代碼:

//初始化之前執(zhí)行
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
	//如果當(dāng)前初始化的是當(dāng)前ConfigurableEmbeddedServletContainer類(lèi)型的組件
	if(bean instanceof ConfigurableEmbeddedServletContainer) {
		this.postProcessBeforeInitialization((ConfigurableEmbeddedServletContainer)bean);
	}

	return bean;
}

//上面的postProcessBeforeInitialization方法:
private void postProcessBeforeInitialization(ConfigurableEmbeddedServletContainer bean) {
	Iterator var2 = this.getCustomizers().iterator();

	while(var2.hasNext()) {
		//獲取所有的定制器,調(diào)用每一個(gè)定制器的customize方法來(lái)給servlet屬性賦值。
		EmbeddedServletContainerCustomizer customizer = (EmbeddedServletContainerCustomizer)var2.next();
		customizer.customize(bean);
	}

private Collection<EmbeddedServletContainerCustomizer> getCustomizers() {
	if(this.customizers == null) {
		//this.beanFactory.xx表示從容器中獲取XXCustomizer自定義類(lèi)型的組件
		this.customizers = new ArrayList(this.beanFactory.getBeansOfType(EmbeddedServletContainerCustomizer.class, false, false).values());
		Collections.sort(this.customizers, AnnotationAwareOrderComparator.INSTANCE);
		this.customizers = Collections.unmodifiableList(this.customizers);
	}

	return this.customizers;
}

整理下步驟:
【1】SpringBoot根據(jù)pom.xml中導(dǎo)入的依賴,給容器中添加其對(duì)應(yīng)的嵌入式的服務(wù)容器工廠類(lèi),例如默認(rèn)的Tomcat工廠:EmbeddedServletContainerFactory【TomcatEmbeddedServletContainerFactory】
【2】給容器中某個(gè)組件要?jiǎng)?chuàng)建對(duì)象就會(huì)觸發(fā)后置處理器EmbeddedServletContainerCustomizerBeanPostProcessor,只要是嵌入式的Servlet容器工廠,后置處理器就會(huì)工作(默認(rèn)的ServerProperties也是實(shí)現(xiàn)了此類(lèi)接口的,所以肯定存在相關(guān)配置類(lèi))
【3】后置處理器從容器中獲取所有的EmbeddedServletContainerCustomizer,調(diào)用定制器的定制方法。

五、嵌入式Servlet容器啟動(dòng)原理

根據(jù)上述的流程,我們要研究Servlet容器的啟動(dòng)原理。其實(shí)就是研究什么時(shí)候創(chuàng)建嵌入式的容器工廠和何時(shí)獲取嵌入式的容器并啟動(dòng)Tomcat。獲取嵌入式的Servlet容器工廠的過(guò)程(在new TomcatEmbeddedServletContainerFactory()時(shí)打一個(gè)斷電,查看過(guò)程):
【1】SpringBoot 應(yīng)用啟動(dòng)運(yùn)行 run() 方法。
【2】this.refreshContext(context) 方法:用來(lái)初始化 IOC容器,既創(chuàng)建 IOC容器對(duì)象并初始化IOC容器中的每一個(gè)組件。

protected ConfigurableApplicationContext createApplicationContext() {
	Class<?> contextClass = this.applicationContextClass;
	if(contextClass == null) {
		try {
			//判斷是不是web環(huán)境,是Web環(huán)境引入AnnotationConfigEmbeddedWebApplicationContext,否則引入AnnotationConfigApplicationContext
			contextClass = Class.forName(this.webEnvironment
			?"org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext"
			:"org.springframework.context.annotation.AnnotationConfigApplicationContext");
		} catch (ClassNotFoundException var3) {
			throw new IllegalStateException("Unable create a default ApplicationContext, please specify an ApplicationContextClass", var3);
		}
	}

	return (ConfigurableApplicationContext)BeanUtils.instantiate(contextClass);
}

【3】this.refresh(context):刷新剛才創(chuàng)建好的IOC容器。
【4】this.onRefresh()webIoC容器重寫(xiě)了onRefresh()方法。

protected void onRefresh() {
	super.onRefresh();

	try {
		//重點(diǎn)是創(chuàng)建了嵌入式的Servlet容器
		this.createEmbeddedServletContainer();
	} catch (Throwable var2) {
		throw new ApplicationContextException("Unable to start embedded container", var2);
	}
}

【5】this.createEmbeddedServletContainer()webIOC容器會(huì)創(chuàng)建嵌入式的Servlet容器。

private void createEmbeddedServletContainer() {
	EmbeddedServletContainer localContainer = this.embeddedServletContainer;
	ServletContext localServletContext = this.getServletContext();
	if(localContainer == null && localServletContext == null) {
		// 1、獲取嵌入式的Servlet嵌入式的工廠
		EmbeddedServletContainerFactory containerFactory = this.getEmbeddedServletContainerFactory();
		this.embeddedServletContainer = containerFactory.getEmbeddedServletContainer(
				new ServletContextInitializer[]{this.getSelfInitializer()});
	} 
}

【6】獲取嵌入式工廠后,便可從容器中獲取EmbeddedServletContainerFactory的組件tomcatEmbeddedServletContainerFactory來(lái)創(chuàng)建Tomcat對(duì)象,后置處理器就會(huì)觸發(fā)獲取所有的定制器來(lái)確定Servlet容器的相關(guān)配置。
【7】通過(guò)嵌入式工廠獲取嵌入式容器,如下:

this.embeddedServletContainer = containerFactory.getEmbeddedServletContainer(
                new ServletContextInitializer[]{this.getSelfInitializer()});

● 嵌入式的Servlet容器創(chuàng)建并啟動(dòng)對(duì)象:

public EmbeddedServletContainer getEmbeddedServletContainer(ServletContextInitializer... initializers) {
    //創(chuàng)建對(duì)象
    Tomcat tomcat = new Tomcat();

    //啟動(dòng)對(duì)象
    this.tomcat.start();

● 先啟動(dòng)嵌入式的Servlet容器,再將IOC容器中剩下沒(méi)有創(chuàng)建的對(duì)象進(jìn)行初始化,如下:

    this.onRefresh();
    //啟動(dòng)完嵌入式容器后,后續(xù)還有其他對(duì)象的初始化工作
    this.registerListeners();
    this.finishBeanFactoryInitialization(beanFactory);
    this.finishRefresh();
} catch (BeansException var9) {

六、使用外置的Servlet容器

嵌入式Servlet容器的缺點(diǎn): 默認(rèn)不支持JSP、優(yōu)化和定制比較復(fù)雜。外置Servlet容器:安裝外部的Tomcat,步驟如下:

1)、必須創(chuàng)建一個(gè)war項(xiàng)目,需要手動(dòng)創(chuàng)建目錄(利用Idea快速創(chuàng)建)如下:

?

2)、將嵌入式的Tomcat指定為provide(Idea創(chuàng)建完后,會(huì)自動(dòng)幫我們完成,但我們需要了解)

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-tomcat</artifactId>
	<scope>provided</scope>
</dependency>

3)、需要編寫(xiě)一個(gè)SpringBootServletInitializer的子類(lèi),并調(diào)用configure方法:

public class ServletInitializer extends SpringBootServletInitializer {

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

4)、配置本地的Tomcat,并啟動(dòng)Tomcat即可。(此項(xiàng)目運(yùn)行run()方法是不能啟動(dòng)項(xiàng)目的):需要設(shè)置名稱和本地Tomcat的路徑即可使用外部Servlet。

七、外置服務(wù)器的使用原理

? jar包:執(zhí)行SpringBoot主類(lèi)的main方法,啟動(dòng)并初始化IOC容器且創(chuàng)建嵌入式的Servlet容器。
? war包:?jiǎn)?dòng)服務(wù)器后調(diào)用SpringBootServletInitializer中的configure()方法,加載我們的SpringBoot應(yīng)用并啟動(dòng)。

Servlet3.0規(guī)則:
 1)、服務(wù)器啟動(dòng)后,會(huì)創(chuàng)建當(dāng)前web應(yīng)用中包含的每個(gè)jar內(nèi)的ServletContainerInitializer實(shí)例。
 2)、ServletContainerInitializer的實(shí)現(xiàn)放在jar包的META-INF/services文件夾下(javax.servlet.ServletContainerInitializer:內(nèi)容就是ServletContainerInitializer的全類(lèi)名)
 3)、可以使用@handlesTypes注解,在應(yīng)用啟動(dòng)時(shí)加載我們需要的類(lèi)。

流程: 1)、啟動(dòng)Tomcat后,獲取servlet.ServletContainerInitializer文件如下:其中的內(nèi)容同下:

在這里插入圖片描述

#文件中的內(nèi)容
org.springframework.web.SpringServletContainerInitializer

 2)、進(jìn)入SpringServletContainerInitializer發(fā)現(xiàn)此類(lèi)將@HandlesTypes({WebApplicationInitializer.class})標(biāo)注的所有這個(gè)類(lèi)型的類(lèi)都傳入到onStartup方法中的Set<Class<?>>,并為這些類(lèi)創(chuàng)建實(shí)例。

@HandlesTypes({WebApplicationInitializer.class})
public class SpringServletContainerInitializer implements ServletContainerInitializer {
    //onStartup方法,用來(lái)實(shí)例化感興趣的對(duì)象
    public void onStartup(Set<Class<?>> webAppInitializerClasses, ServletContext servletContext) throws ServletException {
        if(webAppInitializerClasses != null) {
            var4 = webAppInitializerClasses.iterator();

            while(var4.hasNext()) {
                Class<?> waiClass = (Class)var4.next();
                if(!waiClass.isInterface() && !Modifier.isAbstract(waiClass.getModifiers()) && WebApplicationInitializer.class.isAssignableFrom(waiClass)) {
                    try {
                            //實(shí)例化
                       initializers.add((WebApplicationInitializer)waiClass.newInstance());
                    } catch (Throwable var7) {
                        throw new ServletException("Failed to instantiate WebApplicationInitializer class", var7);
                    }
                }
            }
        }

 3)、每一個(gè)WebApplicationInitializer都調(diào)用自己的onStartup()方法。

while(var4.hasNext()) {
	  WebApplicationInitializer initializer = (WebApplicationInitializer)var4.next();
	  //onStartup()方法
	  initializer.onStartup(servletContext);
 }

 4)、WebApplicationInitializer只是一個(gè)接口,其實(shí)現(xiàn)類(lèi)主要有以下三個(gè):SpringBootServletInitalizer正是SpringBoot給我們創(chuàng)建好的啟動(dòng)類(lèi),會(huì)被創(chuàng)建對(duì)象,并啟動(dòng)自身的onStartup()方法。

 5)、執(zhí)行onStartup()方法時(shí),會(huì)調(diào)用createRootApplicationContext()方法來(lái)創(chuàng)建容器

public void onStartup(ServletContext servletContext) throws ServletException {
        this.logger = LogFactory.getLog(this.getClass());
        //創(chuàng)建容器
        WebApplicationContext rootAppContext = this.createRootApplicationContext(servletContext);
        if(rootAppContext != null) {
            servletContext.addListener(new ContextLoaderListener(rootAppContext) {
                public void contextInitialized(ServletContextEvent event) {
                }
            });

    //容器的具體調(diào)用實(shí)現(xiàn)
    protected WebApplicationContext createRootApplicationContext(ServletContext servletContext) {
        //創(chuàng)建Spring應(yīng)用的構(gòu)建器
        SpringApplicationBuilder builder = this.createSpringApplicationBuilder();
        //設(shè)置主類(lèi)
        builder.main(this.getClass());
        //創(chuàng)建一些環(huán)境
        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)});
        }

        builder.initializers(new ApplicationContextInitializer[]{new ServletContextApplicationContextInitializer(servletContext)});
        builder.contextClass(AnnotationConfigServletWebServerApplicationContext.class);

        //重要:子類(lèi)中重寫(xiě)了此方法,子類(lèi)出入了應(yīng)用的主程序類(lèi)
        builder = this.configure(builder);
        builder.listeners(new ApplicationListener[]{new SpringBootServletInitializer.WebEnvironmentPropertySourceInitializer(servletContext, null)});
        //使用build()創(chuàng)建一個(gè)Spring應(yīng)用
        SpringApplication application = builder.build();
        if(application.getAllSources().isEmpty() && AnnotationUtils.findAnnotation(this.getClass(), Configuration.class) != null) {
            application.addPrimarySources(Collections.singleton(this.getClass()));
        }

        Assert.state(!application.getAllSources().isEmpty(), "No SpringApplication sources have been defined. Either override the configure method or add an @Configuration annotation");
        if(this.registerErrorPageFilter) {
            application.addPrimarySources(Collections.singleton(ErrorPageFilterConfiguration.class));
        }
        //啟動(dòng)應(yīng)用
        return this.run(application);
    }

 6)、執(zhí)行應(yīng)用的run()方法,來(lái)啟動(dòng)Spring應(yīng)用并創(chuàng)建IOC容器。

public ConfigurableApplicationContext run(String... args) {
	StopWatch stopWatch = new StopWatch();
	stopWatch.start();
	ConfigurableApplicationContext context = null;
	Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList();
	this.configureHeadlessProperty();
	SpringApplicationRunListeners listeners = this.getRunListeners(args);
	listeners.starting();

	Collection exceptionReporters;
	try {
		ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
		ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
		this.configureIgnoreBeanInfo(environment);
		Banner printedBanner = this.printBanner(environment);
		context = this.createApplicationContext();
		exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, new Object[]{context});
		this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);

		//刷新IOC容器
		this.refreshContext(context);
		this.afterRefresh(context, applicationArguments);
		stopWatch.stop();
		if(this.logStartupInfo) {
			(new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
		}

		listeners.started(context);
		this.callRunners(context, applicationArguments);
	} catch (Throwable var10) {
		this.handleRunFailure(context, var10, exceptionReporters, listeners);
		throw new IllegalStateException(var10);
	}

	try {
		listeners.running(context);
		return context;
	} catch (Throwable var9) {
		this.handleRunFailure(context, var9, exceptionReporters, (SpringApplicationRunListeners)null);
		throw new IllegalStateException(var9);
	}
}

到此這篇關(guān)于SpringBoot實(shí)現(xiàn)嵌入式 Servlet容器的文章就介紹到這了,更多相關(guān)SpringBoot 嵌入式 Servlet容器內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家! 

相關(guān)文章

  • Java用POI解析excel并獲取所有單元格數(shù)據(jù)的實(shí)例

    Java用POI解析excel并獲取所有單元格數(shù)據(jù)的實(shí)例

    下面小編就為大家?guī)?lái)一篇Java用POI解析excel并獲取所有單元格數(shù)據(jù)的實(shí)例。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-10-10
  • 利用棧使用簡(jiǎn)易計(jì)算器(Java實(shí)現(xiàn))

    利用棧使用簡(jiǎn)易計(jì)算器(Java實(shí)現(xiàn))

    這篇文章主要為大家詳細(xì)介紹了Java利用棧實(shí)現(xiàn)簡(jiǎn)易計(jì)算器,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-09-09
  • JAVA面試題之Forward與Redirect的區(qū)別詳解

    JAVA面試題之Forward與Redirect的區(qū)別詳解

    這篇文章主要給大家介紹了在JAVA面試中可能遇到會(huì)遇到的一道題,就是java中Forward與Redirect兩者之前的區(qū)別,文中介紹的非常詳細(xì),對(duì)大家具有一定參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起看看吧。
    2017-05-05
  • Java ThreadLocal的使用詳解

    Java ThreadLocal的使用詳解

    ThreadLocal是線程私有的局部變量存儲(chǔ)容器,可以理解成每個(gè)線程都有自己專屬的存儲(chǔ)容器,用來(lái)存儲(chǔ)線程私有變量。ThreadLocal 在日常開(kāi)發(fā)框架中應(yīng)用廣泛,但用不好也會(huì)出現(xiàn)各種問(wèn)題,本文就此講解一下。
    2021-05-05
  • Java全面解析IO流相關(guān)知識(shí)

    Java全面解析IO流相關(guān)知識(shí)

    這篇文章主要介紹了IO流相關(guān)知識(shí),包括File,字節(jié)流,字符流,特殊操作流(標(biāo)準(zhǔn)輸入流,標(biāo)準(zhǔn)輸出流,對(duì)象序列化與反序列化,properties與IO流結(jié)合)相關(guān)知識(shí)的總結(jié)
    2021-08-08
  • log4j配置失效日志中打印Debug信息問(wèn)題

    log4j配置失效日志中打印Debug信息問(wèn)題

    這篇文章主要介紹了log4j配置失效日志中打印Debug信息問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • Spring Cloud Hystrix線程池不足的解決方法

    Spring Cloud Hystrix線程池不足的解決方法

    這篇文章主要介紹了Spring Cloud Hystrix線程池不足的解決方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-02-02
  • 2種Java刪除ArrayList中的重復(fù)元素的方法

    2種Java刪除ArrayList中的重復(fù)元素的方法

    這篇文章主要介紹了2種Java刪除ArrayList中的重復(fù)元素的方法,感興趣的朋友可以參考下
    2015-08-08
  • SpringBoot整合Mysql和Redis的詳細(xì)過(guò)程

    SpringBoot整合Mysql和Redis的詳細(xì)過(guò)程

    這篇文章主要介紹了SpringBoot整合Mysql和Redis的示例代碼,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-02-02
  • Spring框架七大模塊簡(jiǎn)單介紹

    Spring框架七大模塊簡(jiǎn)單介紹

    這篇文章主要介紹了Spring框架七大模塊簡(jiǎn)單介紹,具有一定參考價(jià)值,需要的朋友可以了解下。
    2017-11-11

最新評(píng)論