spring boot 自动配置原理:找到不同组件的配置文件、配置配置文件的属性文件

13 篇文章 0 订阅
12 篇文章 0 订阅
  1. spring boot 默认会配置的配置文件
  • SpringBootApplication注解是程序入口
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration     //Spring Boot自动配置实现的核心入口
@ComponentScan(excludeFilters = {
   	@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
   	@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
  • EnableAutoConfiguration注解是配置入口
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage  //Indicates that the package containing the annotated class should be registered with
@Import(AutoConfigurationImportSelector.class)   //自动配置导入选择器
public @interface EnableAutoConfiguration {

   String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

   /**
    * Exclude specific auto-configuration classes such that they will never be applied.
    * @return the classes to exclude
    */
   Class<?>[] exclude() default {};

   /**
    * Exclude specific auto-configuration class names such that they will never be
    * applied.
    * @return the class names to exclude
    * @since 1.3.0
    */
   String[] excludeName() default {};

}
  • AutoConfigurationImportSelector的org.springframework.boot.autoconfigure.AutoConfigurationImportSelector#selectImports方法,该方法会被org.springframework.context.annotation.ConfigurationClassParser#processImports调用,关于ConfigurationClassParser是怎么生效的参考我的博客https://blog.csdn.net/tszxlzc/article/details/88113819
@Override
   public String[] selectImports(AnnotationMetadata annotationMetadata) {
   	if (!isEnabled(annotationMetadata)) {
   		return NO_IMPORTS;
   	}
   	AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
   			.loadMetadata(this.beanClassLoader);
   	AnnotationAttributes attributes = getAttributes(annotationMetadata);
   	// 获取可能被自动配置的类名,进入下面代码看实现
   	List<String> configurations = getCandidateConfigurations(annotationMetadata,
   			attributes);
   	configurations = removeDuplicates(configurations);
   	Set<String> exclusions = getExclusions(annotationMetadata, attributes);
   	checkExcludedClasses(configurations, exclusions);
   	configurations.removeAll(exclusions);
   	configurations = filter(configurations, autoConfigurationMetadata);
   	fireAutoConfigurationImportEvents(configurations, exclusions);
   	return StringUtils.toStringArray(configurations);
   }
  • org.springframework.boot.autoconfigure.AutoConfigurationImportSelector#getCandidateConfigurations方法的实现
/**
    * Return the auto-configuration class names that should be considered. By default
    * this method will load candidates using {@link SpringFactoriesLoader} with
    * {@link #getSpringFactoriesLoaderFactoryClass()}.
    * @param metadata the source metadata
    * @param attributes the {@link #getAttributes(AnnotationMetadata) annotation
    * attributes}
    * @return a list of candidate configurations
    */
   protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,
   		AnnotationAttributes attributes) {
   		// getSpringFactoriesLoaderFactoryClass()方法的返回值org.springframework.boot.autoconfigure.EnableAutoConfiguration
   		// 返回的就是spring.factories中org.springframework.boot.autoconfigure.EnableAutoConfiguration的配置值
   	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;
   }

    /**
    * Return the class used by {@link SpringFactoriesLoader} to load configuration
    * candidates.
    * @return the factory class
    */
   protected Class<?> getSpringFactoriesLoaderFactoryClass() {
   	return EnableAutoConfiguration.class;
   }
  • org.springframework.core.io.support.SpringFactoriesLoader#loadFactoryNames方法去读spring.factories文件
/**
    * Load the fully qualified class names of factory implementations of the
    * given type from {@value #FACTORIES_RESOURCE_LOCATION}, using the given
    * class loader.
    * @param factoryClass the interface or abstract class representing the factory
    * @param classLoader the ClassLoader to use for loading resources; can be
    * {@code null} to use the default
    * @see #loadFactories
    * @throws IllegalArgumentException if an error occurs while loading factory names
    */
   public static List<String> loadFactoryNames(Class<?> factoryClass, @Nullable ClassLoader classLoader) {
   	String factoryClassName = factoryClass.getName();
   	return loadSpringFactories(classLoader).getOrDefault(factoryClassName, 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 {
   	// FACTORIES_RESOURCE_LOCATION 的值就是META-INF/spring.factories
   	 //The location to look for factories,   Can be present in multiple JAR files
   	//public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
   		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()) {
   				List<String> factoryClassNames = Arrays.asList(
   						StringUtils.commaDelimitedListToStringArray((String) entry.getValue()));
   				result.addAll((String) entry.getKey(), factoryClassNames);
   			}
   		}
   		cache.put(classLoader, result);
   		return result;
   	}
   	catch (IOException ex) {
   		throw new IllegalArgumentException("Unable to load factories from location [" +
   				FACTORIES_RESOURCE_LOCATION + "]", ex);
   	}
   }
  • META-INF/spring.factories 中的自动配置类
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.cloud.CloudAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\
org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\
org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.ldap.LdapDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.ldap.LdapRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration,\
org.springframework.boot.autoconfigure.elasticsearch.jest.JestAutoConfiguration,\
org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\
org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,\
org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration,\
org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration,\
org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration,\
org.springframework.boot.autoconfigure.hazelcast.HazelcastJpaDependencyAutoConfiguration,\
org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration,\
org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration,\
org.springframework.boot.autoconfigure.influx.InfluxDbAutoConfiguration,\
org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration,\
org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration,\
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration,\
org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration,\
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration,\
org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,\
org.springframework.boot.autoconfigure.jsonb.JsonbAutoConfiguration,\
org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration,\
org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration,\
org.springframework.boot.autoconfigure.ldap.LdapAutoConfiguration,\
org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderValidatorAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,\
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration,\
org.springframework.boot.autoconfigure.reactor.core.ReactorCoreAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.SecurityRequestMatcherProviderAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration,\
org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.reactive.ReactiveUserDetailsServiceAutoConfiguration,\
org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration,\
org.springframework.boot.autoconfigure.session.SessionAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2ClientAutoConfiguration,\
org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration,\
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration,\
org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration,\
org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.error.ErrorWebFluxAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.reactive.WebSocketReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.servlet.WebSocketServletAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.servlet.WebSocketMessagingAutoConfiguration,\
org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration
  1. 找一个配置类看下,这里选org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration
/**
 * {@link EnableAutoConfiguration Auto-configuration} for a JNDI located
 * {@link DataSource}.
 *
 * @author Phillip Webb
 * @author Andy Wilkinson
 * @since 1.2.0
 */
@Configuration
@AutoConfigureBefore({ XADataSourceAutoConfiguration.class,
		DataSourceAutoConfiguration.class })
// ConditionalOnClass注解很重要,当DataSource.class 或EmbeddedDatabaseType.class在classpath路径下时,本配置类才会生效,所以平时很多组件我盟没有用到启动时也不会报错
@ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class })  
@ConditionalOnProperty(prefix = "spring.datasource", name = "jndi-name")
// 本配置类依赖的配置属性文件,本配置的属性文件就在DataSourceProperties类中
@EnableConfigurationProperties(DataSourceProperties.class)
public class JndiDataSourceAutoConfiguration {

	private final ApplicationContext context;

	public JndiDataSourceAutoConfiguration(ApplicationContext context) {
		this.context = context;
	}

	@Bean(destroyMethod = "")
	@ConditionalOnMissingBean
	public DataSource dataSource(DataSourceProperties properties) {
		JndiDataSourceLookup dataSourceLookup = new JndiDataSourceLookup();
		DataSource dataSource = dataSourceLookup.getDataSource(properties.getJndiName());
		excludeMBeanIfNecessary(dataSource, "dataSource");
		return dataSource;
	}

	private void excludeMBeanIfNecessary(Object candidate, String beanName) {
		for (MBeanExporter mbeanExporter : this.context
				.getBeansOfType(MBeanExporter.class).values()) {
			if (JmxUtils.isMBean(candidate.getClass())) {
				mbeanExporter.addExcludedBean(beanName);
			}
		}
	}

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值