SpringBoot自动装配原理

结论:
springBoot所有的自动配置都在启动类中启动时被扫描并加载:‘spring.factories’所有的自动配置类都在这里面,但是不一定生效,要判断条件是否成立,只要导入对应的start,就有对应的启动器,我们的自动装配就会生效,然后就配置成功了

  1. springBoot在启动时侯,从类路径下/META-INF/spring.factories获取指定的值
  2. 将这些自动配置的类导入容器,自动配置就会生效,帮我们自动进行配置
  3. 以前需要自动配置的东西,现在springBoot帮我们做了
  4. 整合javaee,解决方案和自动配置的东西都在spring-boot-autoconfigure这个包下
  5. 它会把所有需要导入的组件,以类名的方式返回,这些组件就会被添加到容器
  6. 容器中也会存在非常多的***AutoConiguration的文件(@Bean),就是这些类给容器导入了这个场景需要的所有组件,并自动配置@Configuration,javaConfigure
  7. 有了自动配置类,免去了我们手动编写配置文件的工作

以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类中封装着,配置文件能配置什么属性就需要参照某个功能对应的这个属性类

总结:

  1. SpringBoot启动时会加载大量的自动配置类
  2. 我们看我们需要的功能有没有在SpringBoot默认写好的自动配置类(xxxAutoConfiguration类)中
  3. 我们再来看这个自动配置类(xxxAutoConfiguration类)中到底配置了哪些组件(只要我们要用的组件存在其中,我们就不需要手动配置了)
  4. 给容器中自动配置类添加组件的时候,会从properties类中获取某些属性,我们只需要在配置文件中指定这些属性的值即可

xxxAutoConfiguration:自动配置类,给容器中添加组件

xxxProperties:封装配置文件的相关属性

可以通过配置配置文件中debug=true查看哪些自动配置类生效了

  • Positive matches:生效的自动配置类
  • Negative matches:未生效的自动配置类
  • Unconditional classes:没有条件的类
posted @ 2021-11-30 21:29  一刹流云散  阅读(111)  评论(0编辑  收藏  举报