开发者学堂课程【SpringBoot快速掌握 - 核心技术:嵌入式 Servlet 容器自动配置原理】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/612/detail/9261
嵌入式 Servlet 容器自动配置原理
基本内容
一、嵌入式 Servlet 容器自动配置原理
二、步骤
一、嵌入式 Servlet 容器自动配置原理
问:嵌入式 Servlet 容器自动配置原理=嵌入式 Servlet 容器是怎样配置上去?是怎样工作的?
答:参照springBoot里面的自动配置包-web 块-观察名字:嵌入式 Servlet 容器自动配置-接下来观察 直接“1.范例”这个类。
1.范例(嵌入式Servlet容器自动配置):
@AutoConfigureorder (Ordered . HIGHEST PRECEDENCE)
@Configuration
@Conditional0nWebApplication
@Import(BeanPostProcessorsRegistrar.class)
public class EmbeddedServletContainerAutoConfiguration {
//在web应用下,EmbeddedServletContainerAutoConfiguration自动配置才生效。
//导入BeanPostProcessorsRegistar,叫做后置处理器的配置器,
在spring注解版里有详细的介绍。
作用:给容器中导入一些组件。
//导入了EmbeddedServletContainerAutoConfiguration叫做后置处理器
//后置处理器的作用:bean初始化前后(创建完对象,还没有进行属性赋值)开始执行初始化工作。
@Configuration
@Conditiona
l
0nClass({ Servlet. class, Tomcat.class })
//它的作用是判断当前是否引入了Tomcat依赖; @ConditionalonMissingBean(value=EmbeddedServletCcontainerFactory.class, search =SearchStrategy.CURRENT)
//判断当前容器中没有用户自己定义的
EmbeddedServletContainerFactory
(
嵌入式的Servlet容器工厂);作用:创建嵌入式的Servlet容器
public static class EmbeddedTomcat {
@Bean
publicTomcatEmbeddedServletContainerFactory
tomcatEmbeddedServletContainerFactory()
{
return new TomcatEmbeddedServletContainerFactory();
}
}
/*
*
*
Nested configuration if Undertow is being used.
*/
@Configuration
@Conditional0nClass(
{
Servlet.class,Undertow.class,SslClientAuthMode.class
}
)
@ConditionalOnMissingBean(value=EmbeddedServletContainerFactory.
class
.
search.SearchStrategy CURRENT )
public static class EmbeddedUndertow
{
@Bean
public
UndertowEmbeddedServletContainerFactory
undertowEmbeddedServletContainerFactory()
{
return new UndertowEmbeddedServletContainerFactory();
}
}
l 1)EmbeddedServletCcontainerFactory(嵌入式Servlet容器工厂)
这个工厂定义了一个方法,方法如下:
public interface EmbeddedServletContainerFactory
{
//唯一的一个方法:获取嵌入式的Servlet容器
EmbeddedServletContainerget
EmbeddedServletContainer
(ServletContextInitializer... initializers);
}
2 )EmbeddedServletContainer:
( 嵌入式的Servlet容器)
2.自动配置原理:
l 如果是Servlet tomcat 一类,相当于导了tomcat 一类,就会创建一个tomcat Servlet的嵌入式工厂。
l 如果是导了 jetty 一类,像 Servlet 一类都是 jetty 包下的一类,如果导入了 jetty 一类,就帮助放一个 jetty 的工厂。
l 如果是导入了 Undertow,就帮助放一个 Undertow 的嵌入式 Servlet 容器工厂。
l 这里有一个判断,正好这个判断就形成了之前要切换容器的时候,现在只需要把tomcat 依赖移除,导入 jetty,那相当于 Jetty 这段配置就生效了,导入 Undertow那么 Undertow 这个配置生效;
即 以上这三段程序来配置各种嵌入式的容器工厂。
3.以 TomcatEmbeddedServletContaierFactory
为例:
@override Public EmbeddedServletContainer getEmbeddedServletcontainer(
ServletContextInitializer... initializers) {
//创建一个Tomcat
Tomcat tomcat = new Tomcat();
//配置Tomcat的基本环节
File baseDir = (this.baseDirectory != null ? this. baseDirectory
:createTempDir("tomcat"));
tomcat.setBaseDir(baseDir . getAbsolutePath());
Connector connector = new Connector(this. protocol);
tomcat. getService() . addConnector( connector);
customizeConnector(connector);
tomcat . setConnector( connector);
tomcat . getHost(). setAutoDeploy(false);
configureEngine( tomcat. getEngine());
for (Connector additionalConnector:this.additionalTomcatConnectors) {
tomcat.getService().addConnector(additionalConnector);
}
prepareContext(tomcat . getHost(), initializers);
//将配置好的Tomcat传入进去,返回一个EmbeddedServletContainer;并且启动Tomcat服务器
return getTomcatEmbeddedServletContainer(tomcat);
}
4.对嵌入式容器的配置的修改怎么生效
修改时有两种方式,
l 一种是改配置文件里面和Servlet有关的属性,它是和Servletproperties绑定的;
l 第二种是自主放一个嵌入式容器的定制器EmbeddedServletContainerCustomizer
第一种ServerProperties
第二种EmbeddedServletContainerCustomizer
5. EmbeddedServletContainerCustomizer :
定制器帮我们修改了Servlet容器的配置? 修改的原理是什么?
在容器中导入EmbeddedServletContainerCustomizerBeanPostProcessor
//这段代码就是在初始化之前对对象进行创建还没有赋值
@Override
public Object postProgessBeforeInitialization(
o
bject bean,String beanName)
throws BeansException
{
//判断如果当前初始化的是一个ConfigurableEmbedded
ServletContainer
类型的组件
if (bean instanceof ConfigurableEmbeddedServletContainer)
{
//
postProcessBeforeInitialization((ConfigurableEmbeddedServletContainer)bean
)
}
return bean;
}
private void postProcessBeforeInitialization ( ConfigurableEmbeddedServletContainer bean ) {
//获取所有的定制器,调用每一个定制器的customize方法来给Servlet容器进行属性赋值;
for(EmbeddedServletContainerCustomizer cusfomizer:getCustomizers()){
customizer . customize(bean);
}
}
private Collection
getcustomizers() {
if (this.customizers == null) {
//Look up does not include the parent context
this.customizers.new ArrayList(
this . beanFactory
//从容器中获取所有这葛类型的组件: EmbeddedServletContainerCustomizer
//定制Servlet容器,给容器中可以添加一个EmbeddedServletContainerCustomizer类型的组件,定制完成。.getBeansOfType(EmbeddedServletContainerCustomizer.class,false,false)
.values( ) ) ;
Collections.sort(this.customizers,AnnotationAware0rderComparator.INSTANCE)
this.customizers.Collections.unmodifiableList(this.customizers);
}
return this. customizers ;
}
6.ServerProperties也是定制器
二、步骤
1、SpringBoot根据导入的依赖情况,给容器中添加相应的
EmbeddedServletContainerFactory
比如【
TomcatEmbeddedServletContainerFactory
】
2、只要容器中某个组件要创建对象就会惊动后置处理器;
EmbeddedServletContainerCustomizerBeanPostProcessor
;只要是嵌入式的Servlet容器工厂,后置处理器就工作。
3、后置处理器,从容器中获取所有的EmbeddedServletContainer
Customizer
,调用定制器的定制方法
三个步骤完成之后,定制器便会启动。