助力软件开发企业降本增效 PHP / java源码系统,只需一次付费,代码终身使用! 广告
SpringBoot 的精髓就是可以自动配置,减少了开发人员编写配置文件的工作量,提高开发效率。 <br/> SpringBoot提供了哪些自动配置参考[官方文档](https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#appendix)。 <br/> SpringBoot能够实现自动配置,是因为它通过一个过程最终找到了文件`META-INF/spring.factories`,并读取该文件提供的配置插件来完成自动配置,在创建 SpringBoot 项目后,你可以如下图查看提供了哪些自动配置。 ![](https://img.kancloud.cn/dc/fb/dcfbeea3f1f031abcc29a82970be7542_1857x429.jpg) <br/> 它的自动配置原理如下,通过启动类上的`@SpringBootApplication`入口找到下面的过程: ``` 当SpringBoot启动后,它通过下面的过程来加载自动配置 @SpringBootApplication -> @EnableAutoConfiguration -> @Import({AutoConfigurationImportSelector.class}) -> AutoConfigurationImportSelector.selectImports(...) -> getAutoConfigurationEntry(...) -> List<String> configurations = getCandidateConfigurations(...) ->getCandidateConfigurations(...)->SpringFactoriesLoader.loadFactoryNames(...) -> SpringFactoriesLoader.loadSpringFactories(...)-> classLoader.getResources("META-INF/spring.factories") -> AutoConfigurationImportSelector.getCandidateConfigurations(...)-> List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), -> protected Class<?> getSpringFactoriesLoaderFactoryClass() { return EnableAutoConfiguration.class; } 最终方法返回EnableAutoConfiguration.class,将该类的所有组件加入到容器中 -> META-INF/spring.factories -> # Auto Configure org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration,\ ``` 找到`META-INF/spring.factories`文件中的自动配置组件,将这些组件加入到容器中,使得这些组件起作用。 <br/> 下面我们选取HttpEncodingAutoConfiguration这个自动配置组件来研究下,它的部分源码如下: ```java // 配置类,与application.properties,或application.yml配置文件是同等效果 @Configuration( proxyBeanMethods = false ) // 将ServerProperties类中的相关配置加载到当前配置中 // 点击ServerProperties.class进去后,你会看到很多待配置的属性 // ServerProperties中属性与配置文件中的属性对应起来,并获取配置文件中相应属性的值 @EnableConfigurationProperties({ServerProperties.class}) // 底层是Spring的@Conditional注解,根据当前的应用程序是不是Web应用, // 是则让HttpEncodingAutoConfiguration这个配置类生效,否则不让生效 @ConditionalOnWebApplication( type = Type.SERVLET ) // 判断当前项目中是否有CharacterEncodingFilter这个类,有则让这个类生效 // CharacterEncodingFilter是我们在学习SpringMVC时用来处理中文乱码的过滤器 @ConditionalOnClass({CharacterEncodingFilter.class}) // 判断配置文件中是否存在server.servlet.encoding配置,它的默认值为enabled // 而matchIfMissing为true表示不论是否存在server.servlet.encoding配置 // 都让HttpEncodingAutoConfiguration这个配置类生效 @ConditionalOnProperty( prefix = "server.servlet.encoding", value = {"enabled"}, matchIfMissing = true ) // 这个自动用一句话概括就是:根据条件来决定是否让这个配置生效 public class HttpEncodingAutoConfiguration { private final Encoding properties; // 通过自身的构造器获取ServerProperties,然后提供给自身 public HttpEncodingAutoConfiguration(ServerProperties properties) { this.properties = properties.getServlet().getEncoding(); } // 当上面的@ConditionalOnWebApplication、@ConditionalOnClass //、@ConditionalOnProperty三个条件都成立后。@Bean就会往容器中添加 // CharacterEncodingFilter组件,这个组件属性的值从ServerProperties中获取 @ConditionalOnMissingBean // 如果CharacterEncodingFilter还没有被注入容器中,则将其注入并让这个组件生效 public CharacterEncodingFilter characterEncodingFilter() { CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter(); filter.setEncoding(this.properties.getCharset().name()); filter.setForceRequestEncoding(this.properties.shouldForce(org.springframework.boot.web.servlet.server.Encoding.Type.REQUEST)); filter.setForceResponseEncoding(this.properties.shouldForce(org.springframework.boot.web.servlet.server.Encoding.Type.RESPONSE)); return filter; } ``` ServerProperties的部分源码如下,我们可以看到有许多的配置属性: ```java @ConfigurationProperties( prefix = "server", ignoreUnknownFields = true ) public class ServerProperties { private Integer port; private InetAddress address; @NestedConfigurationProperty private final ErrorProperties error = new ErrorProperties(); private ServerProperties.ForwardHeadersStrategy forwardHeadersStrategy; private String serverHeader; private DataSize maxHttpHeaderSize = DataSize.ofKilobytes(8L); private Shutdown shutdown; ``` 总结如下: 在每个XXXAutoConfiguration类中,都会通过@EnableConfigurationProperties将相应的XXXProperties类加载到当前的XXXAutoConfiguration类中,而XXXProperties类上相应的属性已与`application.properties`,或`application.yml`配置文件绑定,可以获取配置文件中的属性值。XXXAutoConfiguration使用@Bean和 @ConditionalOnMissingBean将它加入到容器中,所以最终可以读取到配置文件中配置信息并使自身起作用。 <br/> SpringBoot的精髓就是可以自动配置,减少了开发人员编写大量配置文件的工作量,提高开发效率。所以我们应该如下应用SpringBoot的自动配置: 1. SpringBoot启动会加载大量的自动配置类; 2. 我们看我们需要的功能SpringBoot有没有已经帮我们默认自动配置了; 3. 我们再来看这个自动配置类中到底配置了哪些组件,如果没有我们要的配置组件,则再由我们自定义; 4. 给容器中的自动配置类添加组件的时候,会从XXXProperties类中获取某些属性,这些属性我们就可以在`application.properties`或`application.yml`中进行指定; 5. 通过封装XXXProperties类与配置文件进行绑定,然后加载到XXXAutoconfig类中让这些属性起作用。