@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Configuration
@EnableAutoConfiguration//开启自启动程序
@ComponentScan
public @interface SpringBootApplication {
Class<?>[] exclude() default {};
String[] excludeName() default {};
@AliasFor(
annotation = ComponentScan.class,
attribute = "basePackages"
)
String[] scanBasePackages() default {};
@AliasFor(
annotation = ComponentScan.class,
attribute = "basePackageClasses"
)
Class<?>[] scanBasePackageClasses() default {};
}
SpringBootApplication注解的实现
然后分析EnableAutoConfiguration注解
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({EnableAutoConfigurationImportSelector.class})//加载需要自启动的配置文件
public @interface EnableAutoConfiguration {
Class<?>[] exclude() default {};
String[] excludeName() default {};
}
springboot原理,就是使用SpingFactoriesLoader.loadFactoryNames 扫描具有META-INFO/spring.factories文件的jar包 。
加载容器的配置文件 EmbeddedServletContainerAutoConfiguration,在配置文件中,内置tomcat(满足tomcat容器条件的bean存在),只要满足Jetty、Undertow的条件,可以切换为其他容器。
//EmbeddedServletContainerAutoConfiguration 源码
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@Configuration
@ConditionalOnWebApplication
@Import(BeanPostProcessorsRegistrar.class)
public class EmbeddedServletContainerAutoConfiguration {
/**
* Nested configuration if Tomcat is being used.
*/
@Configuration //tomcat启动条件(springboot内置存在)
@ConditionalOnClass({ Servlet.class, Tomcat.class })
@ConditionalOnMissingBean(value = EmbeddedServletContainerFactory.class, search = SearchStrategy.CURRENT)
public static class EmbeddedTomcat {
@Bean
public TomcatEmbeddedServletContainerFactory tomcatEmbeddedServletContainerFactory() {
return new TomcatEmbeddedServletContainerFactory();
}
}
/**
* Nested configuration if Jetty is being used.
*/
@Configuration //jetty启动条件 :导入相应的pom文件即可
@ConditionalOnClass({ Servlet.class, Server.class, Loader.class,
WebAppContext.class })
@ConditionalOnMissingBean(value = EmbeddedServletContainerFactory.class, search = SearchStrategy.CURRENT)
public static class EmbeddedJetty {
@Bean
public JettyEmbeddedServletContainerFactory jettyEmbeddedServletContainerFactory() {
return new JettyEmbeddedServletContainerFactory();
}
}
/**
* Nested configuration if Undertow is being used.
*/
@Configuration //Undertow 启动条件
@ConditionalOnClass({ Servlet.class, Undertow.class, SslClientAuthMode.class })
@ConditionalOnMissingBean(value = EmbeddedServletContainerFactory.class, search = SearchStrategy.CURRENT)
public static class EmbeddedUndertow {
@Bean
public UndertowEmbeddedServletContainerFactory undertowEmbeddedServletContainerFactory() {
return new UndertowEmbeddedServletContainerFactory();
}
}
以tomcat为例,继续看如何加载并配置servlet容器 TomcatEmbeddedServletContainerFactory 获取容器
@Override
public EmbeddedServletContainer getEmbeddedServletContainer(
ServletContextInitializer... initializers) {
Tomcat tomcat = new Tomcat();
File baseDir = (this.baseDirectory != null ? this.baseDirectory
: createTempDir("tomcat"));
tomcat.setBaseDir(baseDir.getAbsolutePath());
//通过nio1连接 org.apache.coyote.http11.Http11NioProtocol
Connector connector = new Connector(this.protocol);
tomcat.getService().addConnector(connector);
customizeConnector(connector); //connector 个性化配置 //模板设计模式
tomcat.setConnector(connector);
tomcat.getHost().setAutoDeploy(false);
configureEngine(tomcat.getEngine());
for (Connector additionalConnector : this.additionalTomcatConnectors) {
tomcat.getService().addConnector(additionalConnector);
}
prepareContext(tomcat.getHost(), initializers);
return getTomcatEmbeddedServletContainer(tomcat);
}
继续跟踪查看customizeConnector(connector);
查看此方法源码 所以有两种方式可以实现个性化的connector
1.继承 TomcatEmbeddedServletContainerFactory 重写此方法,加入个性化配置
2.实现TomcatConnectorCustomizer 接口,将实现类加入到TomcatEmbeddedServletContainerFactory
for (TomcatConnectorCustomizer customizer : this.tomcatConnectorCustomizers) {
customizer.customize(connector); //个性化配置的主要接口
}
//添加个性化connector类 TomcatConnectorCustomizer
public void addConnectorCustomizers(
TomcatConnectorCustomizer... tomcatConnectorCustomizers) {
Assert.notNull(tomcatConnectorCustomizers,
"TomcatConnectorCustomizers must not be null");
this.tomcatConnectorCustomizers.addAll(Arrays.asList(tomcatConnectorCustomizers));
}
TomcatConnectorCustomizer 自定义个性化connector(实现此类后,将实现类接入到factory中即可)
public interface TomcatConnectorCustomizer {
/**
* Customize the connector.
* @param connector the connector to customize
*/
void customize(Connector connector);
}