Spring Boot自动配置源码
来源:互联网 发布:qq mac版手机 编辑:程序博客网 时间:2024/06/05 21:03
SpringBoot初始化上下文环境
SpringBoot会从META-INF/spring.factories
文件中加载Initializers,Auto Configure
Initializers用于加载配置(Environment)
Auto Configure用于自动配置类
如果是web类型的工程,SpringBoot会创建EmbeddedWebApplicationContext上下文 -> 使用createEmbeddedServletContainer方法创建内嵌的servlet服务容器( 由工厂类EmbeddedServletContainerFactory -> getEmbeddedServletContainer()创建Servlet容器, ->initialize() 同时进行容器初始化及运行 )
容器类EmbeddedServletContainer控制着内嵌服务器的生命周期以及配置.
加载AutoConfiguration
AutoConfiguration初始化对应的实例
我们来看下Mongo的AutoConfiguration,如下:
@Configuration@ConditionalOnClass(MongoClient.class)@EnableConfigurationProperties(MongoProperties.class)@ConditionalOnMissingBean(type = "org.springframework.data.mongodb.MongoDbFactory")public class MongoAutoConfiguration { @Autowired private MongoProperties properties; @Autowired(required = false) private MongoClientOptions options; @Autowired private Environment environment; private MongoClient mongo; @PreDestroy public void close() { if (this.mongo != null) { this.mongo.close(); } } @Bean @ConditionalOnMissingBean public MongoClient mongo() throws UnknownHostException { this.mongo = this.properties.createMongoClient(this.options, this.environment); return this.mongo; }}
Mongo的AutoConfiguration将会在用户引入Mongo相关包时,并且没有自定义MongoDbFactory时被激活,同时配置文件(application.properties之类的)将注入到MongoProperties中.MongoProperties类由@ConfigurationProperties标注:
@ConfigurationProperties(prefix = "spring.data.mongodb")public class MongoProperties { /** * Default port used when the configured port is {@code null}. */ public static final int DEFAULT_PORT = 27017; /** * Mongo server host. */ private String host; //...省略... //根据配置创建MongoClient public MongoClient createMongoClient(MongoClientOptions options, Environment environment) throws UnknownHostException { try { if (hasCustomAddress() || hasCustomCredentials()) { if (options == null) { options = MongoClientOptions.builder().build(); } List<MongoCredential> credentials = null; if (hasCustomCredentials()) { String database = this.authenticationDatabase == null ? getMongoClientDatabase() : this.authenticationDatabase; credentials = Arrays.asList(MongoCredential.createMongoCRCredential( this.username, database, this.password)); } String host = this.host == null ? "localhost" : this.host; int port = determinePort(environment); return new MongoClient(Arrays.asList(new ServerAddress(host, port)), credentials, options); } // The options and credentials are in the URI return new MongoClient(new MongoClientURI(this.uri, builder(options))); } finally { clearPassword(); } }
可以看到MongoClient最终由MongoAutoConfiguration调用MongoProperties的createMongoClient()方法创建.通过标注@Bean将MongoClient发布到Spring容器中.
如果用户已经用@Bean自定义了一个MongoClient,那么Mongo AutoConfig就不会做去初始化MongoClient,配置文件中的配置也就不生效了.
Embedded Tomcat初始化过程
内嵌式Tomcat通过Tomcat类创建并配置的,我们可以看看Spring是如何包装的,使用工厂类TomcatEmbeddedServletContainerFactory -> getEmbeddedServletContainer() :
@Override public EmbeddedServletContainer getEmbeddedServletContainer( ServletContextInitializer... initializers) { //通常创建内嵌Tomcat时的流程,使用Tomcat类 Tomcat tomcat = new 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); tomcat.getEngine().setBackgroundProcessorDelay(-1); for (Connector additionalConnector : this.additionalTomcatConnectors) { tomcat.getService().addConnector(additionalConnector); } prepareContext(tomcat.getHost(), initializers); return getTomcatEmbeddedServletContainer(tomcat); }
Spring使用EmbeddedServletContainer包装了Tomcat,封装了内嵌容器的生命周期.
所有用户通过工厂类EmbeddedServletContainerFactory配置容器,例如:application.properties中的server.port=8099
,
带有@ConfigurationProperties注解的ServerProperties,自动注入了application.properties中关于server.*的配置.
由于ServerProperties实现了EmbeddedServletContainerCustomizer接口,ServerProperties通过该接口的方法,对EmbeddedServletContainerFactory进行配置:
if (getPort() != null) { container.setPort(getPort()); } if (getAddress() != null) { container.setAddress(getAddress()); } if (getContextPath() != null) { container.setContextPath(getContextPath()); } if (getDisplayName() != null) { container.setDisplayName(getDisplayName()); } if (getSession().getTimeout() != null) { container.setSessionTimeout(getSession().getTimeout()); } if (getSsl() != null) { container.setSsl(getSsl()); } if (getJspServlet() != null) { container.setJspServlet(getJspServlet()); } if (getCompression() != null) { container.setCompression(getCompression()); }
除了配置文件方式,我们还可以:
@Bean public EmbeddedServletContainerFactory servletContainer() { TomcatEmbeddedServletContainerFactory factory = new TomcatEmbeddedServletContainerFactory(); factory.addConnectorCustomizers(connector -> { Http11NioProtocol protocol = ((Http11NioProtocol) connector.getProtocolHandler()); connector.setPort(8989); protocol.setConnectionTimeout(10000); }); return factory; }
直接自己创建工厂类,并实现addConnectorCustomizers接口中的customizer.这部分会覆盖配置文件的配置,在TomcatEmbeddedServletContainerFactory的getEmbeddedServletContainer() -> customizeConnector() 中会调用我们自定义的customizer:
for (TomcatConnectorCustomizer customizer : this.tomcatConnectorCustomizers) { customizer.customize(connector); }
如果用户没有自定义EmbeddedServletContainerFactory的话,EmbeddedServletContainerAutoConfiguration就默认初始化一个.
@Configuration @ConditionalOnClass({ Servlet.class, Tomcat.class }) @ConditionalOnMissingBean(value = EmbeddedServletContainerFactory.class, search = SearchStrategy.CURRENT) public static class EmbeddedTomcat { @Bean public TomcatEmbeddedServletContainerFactory tomcatEmbeddedServletContainerFactory() { return new TomcatEmbeddedServletContainerFactory(); } }
Reference
http://geowarin.github.io/understanding-spring-boot.html
http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#howto-troubleshoot-auto-configuration
http://blog.csdn.net/liaokailin/article/category/5765237
- Spring Boot自动配置源码
- 【Spring Boot】SpringBoot-自动配置源码解析
- spring boot自动配置
- Spring Boot自动配置
- Spring Boot自动配置实例
- Spring boot 自动配置套路
- Spring Boot自动配置实战
- spring boot spring mvc 自动配置类
- [Spring Boot] 3. Spring Boot实现自动配置的基础
- [Spring Boot] 4. Spring Boot实现自动配置的原理
- 3Spring Boot 运行原理,自动配置
- Spring Boot核心原理-自动配置
- Spring Boot核心原理-自动配置
- Spring Boot核心原理-自动配置
- spring boot 1.5.2自动配置kafka
- Spring Boot 运行原理之自动配置
- Spring Boot实现自动配置的基础
- Spring Boot自动配置原理、实战
- unicode字符集的查询网站
- Qt中通过控件在Label标签中显示一张静态图片
- JNI生成.h文件 找不到' '的类文件
- 【NCRE】——c#判断ppt中的艺术字
- leetcode Path Sum II
- Spring Boot自动配置源码
- macpro 装Ubuntu15 虚拟机 字太小的调节方法
- 检测文件中是否存在bom
- XSS攻击测试语句
- LeetCode OJ 系列之1 Two Sum --Python
- Android Studio Tips-倍数提高工作效率的Android Studio奇技
- Oracle视图
- 基于JQUERY的WEB在线流程图设计器GOOFLOW 0.5版
- Android 键盘使用一(监听弹出隐藏)