SpringBoot自动装配原理
结论:
springBoot所有的自动配置都在启动类中启动时被扫描并加载:‘spring.factories’所有的自动配置类都在这里面,但是不一定生效,要判断条件是否成立,只要导入对应的start,就有对应的启动器,我们的自动装配就会生效,然后就配置成功了
- springBoot在启动时侯,从类路径下/META-INF/spring.factories获取指定的值
- 将这些自动配置的类导入容器,自动配置就会生效,帮我们自动进行配置
- 以前需要自动配置的东西,现在springBoot帮我们做了
- 整合javaee,解决方案和自动配置的东西都在spring-boot-autoconfigure这个包下
- 它会把所有需要导入的组件,以类名的方式返回,这些组件就会被添加到容器
- 容器中也会存在非常多的***AutoConiguration的文件(@Bean),就是这些类给容器导入了这个场景需要的所有组件,并自动配置@Configuration,javaConfigure
- 有了自动配置类,免去了我们手动编写配置文件的工作
以Spring.factories中的HttpEncodingAutoConfiguration为例
@Configuration(proxyBeanMethods = false) //表示这是一个配置类
@EnableConfigurationProperties(ServerProperties.class) //自动配置的配置属性
//Spring的底层注解:根据不同的条件来判断当前配置或者类是否生效
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
@ConditionalOnClass(CharacterEncodingFilter.class)
@ConditionalOnProperty(prefix = "server.servlet.encoding", value = "enabled", matchIfMissing = true)
public class HttpEncodingAutoConfiguration {
private final Encoding properties;
public HttpEncodingAutoConfiguration(ServerProperties properties) { //自动配置的配置属性
this.properties = properties.getServlet().getEncoding();
}
@Bean
@ConditionalOnMissingBean //判断是否存在当前这个bean
public CharacterEncodingFilter characterEncodingFilter() {
CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
filter.setEncoding(this.properties.getCharset().name());
filter.setForceRequestEncoding(this.properties.shouldForce(Encoding.Type.REQUEST));
filter.setForceResponseEncoding(this.properties.shouldForce(Encoding.Type.RESPONSE));
return filter;
}
@Bean
public LocaleCharsetMappingsCustomizer localeCharsetMappingsCustomizer() {
return new LocaleCharsetMappingsCustomizer(this.properties);
}
static class LocaleCharsetMappingsCustomizer
implements WebServerFactoryCustomizer<ConfigurableServletWebServerFactory>, Ordered {
private final Encoding properties;
LocaleCharsetMappingsCustomizer(Encoding properties) {
this.properties = properties;
}
@Override
public void customize(ConfigurableServletWebServerFactory factory) {
if (this.properties.getMapping() != null) {
factory.setLocaleCharsetMappings(this.properties.getMapping());
}
}
@Override
public int getOrder() {
return 0;
}
}
}
ServerProperties
@ConfigurationProperties(prefix = "server", ignoreUnknownFields = true)
public class ServerProperties {
/**
* Server HTTP port.
*/
private Integer port;
/**
* Network address to which the server should bind.
*/
private InetAddress address;
@NestedConfigurationProperty
private final ErrorProperties error = new ErrorProperties();
/**
* Strategy for handling X-Forwarded-* headers.
*/
private ForwardHeadersStrategy forwardHeadersStrategy;
/**
* Value to use for the Server response header (if empty, no header is sent).
*/
private String serverHeader;
/**
* Maximum size of the HTTP message header.
*/
private DataSize maxHttpHeaderSize = DataSize.ofKilobytes(8);
/**
* Type of shutdown that the server will support.
*/
private Shutdown shutdown = Shutdown.IMMEDIATE;
@NestedConfigurationProperty
private Ssl ssl;
@NestedConfigurationProperty
private final Compression compression = new Compression();
@NestedConfigurationProperty
private final Http2 http2 = new Http2();
private final Servlet servlet = new Servlet();
private final Reactive reactive = new Reactive();
private final Tomcat tomcat = new Tomcat();
private final Jetty jetty = new Jetty();
private final Netty netty = new Netty();
private final Undertow undertow = new Undertow();
public Integer getPort() {
return this.port;
}
public void setPort(Integer port) {
this.port = port;
}
public InetAddress getAddress() {
return this.address;
}
public void setAddress(InetAddress address) {
this.address = address;
}
public String getServerHeader() {
return this.serverHeader;
}
public void setServerHeader(String serverHeader) {
this.serverHeader = serverHeader;
}
....................
....................
....................
....................
}
application.yaml
#配置文件能写什么--------spring-boot-test-autoconfigure-2.6.1.jar!\META-INF\spring.factories 联系
#在我们这些配置文件中能配置的东西,都存在一个固有的规律
#配置文件绑定 默认值与配置文件绑定就可以使用自定义配置了
#xxxProperties 默认值
#xxxAutoConfiguration
debug: true
spring:
activemq:
in-memory:
#可以通过debug=true查看哪个配置类生效
- 每一个这样的xxxAutoConfiguration类都是容器中的一个组件,最后都加入到容器中,用他们来做自动配置
- 每一个自动配置类都可以进行自动配置功能
- 一旦这个配置类生效:这个配置类就会给容器中添加各种组件,这些组件的属性是从对应的properties类中获取的,properties类里面的每一个属性又是和配置文件绑定的
- 所有的配置文件中能配置的属性都是在xxxProperties类中封装着,配置文件能配置什么属性就需要参照某个功能对应的这个属性类
总结:
- SpringBoot启动时会加载大量的自动配置类
- 我们看我们需要的功能有没有在SpringBoot默认写好的自动配置类(xxxAutoConfiguration类)中
- 我们再来看这个自动配置类(xxxAutoConfiguration类)中到底配置了哪些组件(只要我们要用的组件存在其中,我们就不需要手动配置了)
- 给容器中自动配置类添加组件的时候,会从properties类中获取某些属性,我们只需要在配置文件中指定这些属性的值即可
xxxAutoConfiguration:自动配置类,给容器中添加组件
xxxProperties:封装配置文件的相关属性
可以通过配置配置文件中debug=true查看哪些自动配置类生效了
- Positive matches:生效的自动配置类
- Negative matches:未生效的自动配置类
- Unconditional classes:没有条件的类