O princípio da configuração automática da mola [Springboot]

Princípio de configuração automática do Spring

O processo de montagem do arquivo de configuração springboot

1. Springboot carregará a classe de configuração principal quando for iniciado e @EnableAutoConfiguration será ativado.

2. A função de @EnableAutoConfiguration:

  • Use AutoConfigurationImportSelector para importar alguns componentes para o contêiner.
  • Visualize o conteúdo do método selectImports e retorne um AutoConfigurationEntry
AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(autoConfigurationMetadata,
      annotationMetadata);
------
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
------
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
		List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
				getBeanClassLoader());
		Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you "
				+ "are using a custom packaging, make sure that file is correct.");
		return configurations;
	}
  • Você pode ver SpringFactoriesLoader.loadFactoryNames, continuar a ler e chamar o método loadSpringFactories para obter o arquivo de recurso META-INF / spring.factories
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
		String factoryTypeName = factoryType.getName();
		return loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());
	}

	private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
		MultiValueMap<String, String> result = cache.get(classLoader);
		if (result != null) {
			return result;
		}

		try {
			Enumeration<URL> urls = (classLoader != null ?
					classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
					ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
			result = new LinkedMultiValueMap<>();
			while (urls.hasMoreElements()) {
				URL url = urls.nextElement();
				UrlResource resource = new UrlResource(url);
				Properties properties = PropertiesLoaderUtils.loadProperties(resource);
				for (Map.Entry<?, ?> entry : properties.entrySet()) {
					String factoryTypeName = ((String) entry.getKey()).trim();
					for (String factoryImplementationName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {
						result.add(factoryTypeName, factoryImplementationName.trim());
					}
				}
			}
			cache.put(classLoader, result);
			return result;
		}
		catch (IOException ex) {
			throw new IllegalArgumentException("Unable to load factories from location [" +
					FACTORIES_RESOURCE_LOCATION + "]", ex);
		}
	}

Resumo: adicione todos os valores EnableAutoConfiguration configurados em META-INF / spring.factories sob o classpath para o contêiner; cada classe xxxAutoConfiguration é um componente do contêiner e, finalmente, adicionada ao contêiner para configuração automática. Cada classe de configuração automática pode realizar a função de configuração automática

Use HttpEncodingAutoConfiguration para explicar o princípio da montagem automática

/*
表名这是一个配置类,
*/
@Configuration(proxyBeanMethods = false)
/*
启动指定类的ConfigurationProperties功能,进入HttpProperties查看,将配置文件中对应的值和HttpProperties绑定起来,并把HttpProperties加入到ioc容器中
*/
@EnableConfigurationProperties(HttpProperties.class)
/*
spring底层@Confitional注解,根据不同的条件判断,如果满足指定的条件,整个配置类里面的配置就会生效
此时表示判断当前应用是否是web应用,如果是,那么配置类生效
*/
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
/*
判断当前项目由没有这个类CharacterEncodingFilter,springmvc中进行乱码解决的过滤器
*/
@ConditionalOnClass(CharacterEncodingFilter.class)
/*
判断配置文件中是否存在某个配置:spring.http.encoding.enabled
如果不存在,判断也是成立的,
即使我们配置文件中不配置spring.http.encoding.enabled=true,也是默认生效的
*/
@ConditionalOnProperty(prefix = "spring.http.encoding", value = "enabled", matchIfMissing = true)
public class HttpEncodingAutoConfiguration {

    //和springboot的配置文件映射
	private final HttpProperties.Encoding properties;

    //只有一个有参构造器的情况下,参数的值就会从容器中拿
	public HttpEncodingAutoConfiguration(HttpProperties properties) {
		this.properties = properties.getEncoding();
	}

    //给容器中添加一个组件,这个组件的某些值需要从properties中获取
	@Bean
	@ConditionalOnMissingBean//判断容器中是否有此组件
	public CharacterEncodingFilter characterEncodingFilter() {
		CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
		filter.setEncoding(this.properties.getCharset().name());
		filter.setForceRequestEncoding(this.properties.shouldForce(Type.REQUEST));
		filter.setForceResponseEncoding(this.properties.shouldForce(Type.RESPONSE));
		return filter;
	}

	@Bean
	public LocaleCharsetMappingsCustomizer localeCharsetMappingsCustomizer() {
		return new LocaleCharsetMappingsCustomizer(this.properties);
	}

	private static class LocaleCharsetMappingsCustomizer
			implements WebServerFactoryCustomizer<ConfigurableServletWebServerFactory>, Ordered {

		private final HttpProperties.Encoding properties;

		LocaleCharsetMappingsCustomizer(HttpProperties.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;
		}
	}
}

De acordo com as diferentes condições de corrente, determine se esta classe de configuração é eficaz!

Resumindo:

1. Springboot irá carregar um grande número de classes de configuração automática

2. Verifique se as funções necessárias são configuradas automaticamente por padrão no springboot.

3. Verifique quais componentes estão configurados nesta classe de configuração automática

4. Ao adicionar componentes à classe de configuração automática no contêiner, as propriedades serão obtidas na classe de propriedades

@ Condicional: a classe de configuração automática só pode ter efeito sob certas condições

@Anotação estendida condicional efeito
@ConditionalOnJava A versão java do sistema atende aos requisitos?
@ConditionalOnBean O Bean especificado existe no contêiner
@ConditionalOnMissingBean O bean especificado não existe no contêiner
@ConditionalOnExpression Satisfaça a expressão SpEL
@ConditionalOnClass Existem classes especificadas no sistema
@ConditionalOnMissingClass Não há nenhuma classe especificada no sistema
@ConditionalOnSingleCandidate Existe apenas um bean especificado no contêiner, ou o bean preferido
@ConditionalOnProperty Se o atributo especificado no sistema tem o valor especificado
@ConditionalOnResource Se o arquivo de recurso especificado existe no caminho da classe
@ConditionOnWebApplication Atualmente ambiente web
@ConditionalOnNotWebApplication Atualmente não é um ambiente da web
@ConditionalOnJndi JNDI especificou itens

Acho que você gosta

Origin blog.csdn.net/zw764987243/article/details/111879886
Recomendado
Clasificación