SpringBoot自动配置源码
Posted _懒惰的猫
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringBoot自动配置源码相关的知识,希望对你有一定的参考价值。
Spring Boot版本:2.2.4
每个springboot的启动类都有一个@SpringBootApplication注解
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class RabbitmqApplication { public static void main(String[] args) { SpringApplication.run(RabbitmqApplication.class, args); } }
进入@SpringBootApplication注解,发现有一个@EnableAutoConfiguration的注解
package org.springframework.boot.autoconfigure; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.springframework.boot.SpringBootConfiguration; import org.springframework.boot.context.TypeExcludeFilter; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.FilterType; import org.springframework.context.annotation.ComponentScan.Filter; import org.springframework.core.annotation.AliasFor; @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @SpringBootConfiguration @EnableAutoConfiguration @ComponentScan( excludeFilters = {@Filter( type = FilterType.CUSTOM, classes = {TypeExcludeFilter.class} ), @Filter( type = FilterType.CUSTOM, classes = {AutoConfigurationExcludeFilter.class} )} ) public @interface SpringBootApplication { @AliasFor( annotation = EnableAutoConfiguration.class ) Class<?>[] exclude() default {}; @AliasFor( annotation = EnableAutoConfiguration.class ) String[] excludeName() default {}; @AliasFor( annotation = ComponentScan.class, attribute = "basePackages" ) String[] scanBasePackages() default {}; @AliasFor( annotation = ComponentScan.class, attribute = "basePackageClasses" ) Class<?>[] scanBasePackageClasses() default {}; @AliasFor( annotation = Configuration.class ) boolean proxyBeanMethods() default true; }
继续进入@EnableAutoConfiguration注解:
package org.springframework.boot.autoconfigure; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.springframework.context.annotation.Import; @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @AutoConfigurationPackage @Import({AutoConfigurationImportSelector.class}) public @interface EnableAutoConfiguration { String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration"; Class<?>[] exclude() default {}; String[] excludeName() default {}; }
有一个 @Import({AutoConfigurationImportSelector.class}) 注解,这个注解就是用于spirng导入bean的。这个注解内可以传入 ImportSelector 接口的实现类来达到注入bean的效果。进入到AutoConfigurationImportSelector类:
实现了selectImports方法:
public String[] selectImports(AnnotationMetadata annotationMetadata) { if (!this.isEnabled(annotationMetadata)) { return NO_IMPORTS; } else { AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader); AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(autoConfigurationMetadata, annotationMetadata); return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations()); } }
可以看出最后返回的是AutoConfigurationEntry类的configurations属性,而AutoConfigurationEntry类是AutoConfigurationImportSelector的内部类,而AutoConfigurationEntry对象是在 this.getAutoConfigurationEntry(autoConfigurationMetadata, annotationMetadata); 方法中返回的,那么看一下getAutoConfigurationEntry方法:
protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata, AnnotationMetadata annotationMetadata) { if (!this.isEnabled(annotationMetadata)) { return EMPTY_ENTRY; } else { AnnotationAttributes attributes = this.getAttributes(annotationMetadata); List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes); configurations = this.removeDuplicates(configurations); Set<String> exclusions = this.getExclusions(annotationMetadata, attributes); this.checkExcludedClasses(configurations, exclusions); configurations.removeAll(exclusions); configurations = this.filter(configurations, autoConfigurationMetadata); this.fireAutoConfigurationImportEvents(configurations, exclusions); //返回的就是AutoConfigurationImportSelector的内部类:AutoConfigurationEntry,并在构造方法中传入了configurations,这个属性恰恰就是我们最终需要的结果 return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions); } }
在方法的末尾返回了一个有参数的内部类构造方法,我们最终需要的就是构造方法里的configrations,看一下这个参数是在 this.getCandidateConfigurations(annotationMetadata, attributes); 这个方法中返回的,接下来看一下this.getCandidateConfigurations方法:
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) { List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.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; } protected Class<?> getSpringFactoriesLoaderFactoryClass() { return EnableAutoConfiguration.class; }
configurations是通过 SpringFactoriesLoader类的loadFactoryNames方法返回的,并传入了两个值,一个名为SpringFactoriesLoaderFactoryClass,另一个是BeanClassLoader,而在这个方法的下面就是获取SpringFactoriesLoaderFactoryClass值的方法,发现返回了 EnableAutoConfiguration.class。
继续深入,查看SpringFactoriesLoader的loadFactoryNames方法:
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) { //获取EnableAutoConfiguration.class类的名字,即EnableAutoConfiguration类的全路径 String factoryTypeName = factoryType.getName(); //这个loadSpringFactories方法就是下面的方法,将classLoader传入,在返回的LinkedMutiValueMap中取key为EnableAutoConfiguration类全路径的值 return (List)loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList()); } private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) { //如果之前有其他方法加载过此配置文件,那么会存在缓存中,直接在缓存中取即可 MultiValueMap<String, String> result = (MultiValueMap)cache.get(classLoader); if (result != null) { return result; } else { try { //读取META-INF/spring.factories里的数据 Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories"); LinkedMultiValueMap result = new LinkedMultiValueMap(); //并将数据放到LinkedMutiValueMap中(一键多值) while(urls.hasMoreElements()) { URL url = (URL)urls.nextElement(); UrlResource resource = new UrlResource(url); Properties properties = PropertiesLoaderUtils.loadProperties(resource); Iterator var6 = properties.entrySet().iterator(); while(var6.hasNext()) { Entry<?, ?> entry = (Entry)var6.next(); String factoryTypeName = ((String)entry.getKey()).trim(); String[] var9 = StringUtils.commaDelimitedListToStringArray((String)entry.getValue()); int var10 = var9.length; for(int var11 = 0; var11 < var10; ++var11) { String factoryImplementationName = var9[var11]; result.add(factoryTypeName, factoryImplementationName.trim()); } } } //最后将结果放进缓存中,提高效率减少IO cache.put(classLoader, result); return result; } catch (IOException var13) { throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var13); } } }
发现会去读取 META-INF/spring.factories中的名为 org.springframework.boot.autoconfigure.EnableAutoConfiguration 的值:
# Initializers org.springframework.context.ApplicationContextInitializer=\\ org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\\ org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener # Application Listeners org.springframework.context.ApplicationListener=\\ org.springframework.boot.autoconfigure.BackgroundPreinitializer # Auto Configuration Import Listeners org.springframework.boot.autoconfigure.AutoConfigurationImportListener=\\ org.springframework.boot.autoconfigure.condition.ConditionEvaluationReportAutoConfigurationImportListener # Auto Configuration Import Filters org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\\ org.springframework.boot.autoconfigure.condition.OnBeanCondition,\\ org.springframework.boot.autoconfigure.condition.OnClassCondition,\\ org.springframework.boot.autoconfigure.condition.OnWebApplicationCondition # 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.CloudServiceConnectorsAutoConfiguration,\\ 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.elasticsearch.ReactiveElasticsearchRepositoriesAutoConfiguration,\\ org.springframework.boot.autoconfigure.data.elasticsearch.ReactiveRestClientAutoConfiguration,\\ org.springframework.boot.autoconfigure.data.jdbc.JdbcRepositoriesAutoConfiguration,\\ org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\\ 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.elasticsearch.rest.RestClientAutoConfiguration,\\ 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.rsocket.RSocketMessagingAutoConfiguration,\\ org.springframework.boot.autoconfigure.rsocket.RSocketRequesterAutoConfiguration,\\ org.springframework.boot.autoconfigure.rsocket.RSocketServerAutoConfiguration,\\ org.springframework.boot.autoconfigure.rsocket.RSocketStrategiesAutoConfiguration,\\ org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration,\\ 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.security.rsocket.RSocketSecurityAutoConfiguration,\\ org.springframework.boot.autoconfigure.security.saml2.Saml2RelyingPartyAutoConfiguration,\\ org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration,\\ org.springframework.boot.autoconfigure.session.SessionAutoConfiguration,\\ org.springframework.boot.autoconfigure.security.oauth2.client.servlet.OAuth2ClientAutoConfiguration,\\ org.springframework.boot.autoconfigure.security.oauth2.client.reactive.ReactiveOAuth2ClientAutoConfiguration,\\ org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerAutoConfiguration,\\ org.springframework.boot.autoconfigure.security.oauth2.resource.reactive.ReactiveOAuth2ResourceServerAutoConfiguration,\\ org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration,\\ org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration,\\ org.springframework.boot.autoconfigure.task.TaskSchedulingAutoConfiguration,\\ 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.ClientHttpConnectorAutoConfiguration,\\ 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,\\ org.springframework.boot.autoconfigure.webservices.client.WebServiceTemplateAutoConfiguration # Failure analyzers org.springframework.boot.diagnostics.FailureAnalyzer=\\ org.springframework.boot.autoconfigure.diagnostics.analyzer.NoSuchBeanDefinitionFailureAnalyzer,\\ org.springframework.boot.autoconfigure.flyway.FlywayMigrationScriptMissingFailureAnalyzer,\\ org.springframework.boot.autoconfigure.jdbc.DataSourceBeanCreationFailureAnalyzer,\\ org.springframework.boot.autoconfigure.jdbc.HikariDriverConfigurationFailureAnalyzer,\\ org.springframework.boot.autoconfigure.session.NonUniqueSessionRepositoryFailureAnalyzer # Template availability providers org.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider=\\ org.springframework.boot.autoconfigure.freemarker.FreeMarkerTemplateAvailabilityProvider,\\ org.springframework.boot.autoconfigure.mustache.MustacheTemplateAvailabilityProvider,\\ org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAvailabilityProvider,\\ org.springframework.boot.autoconfigure.thymeleaf.ThymeleafTemplateAvailabilityProvider,\\ org.springframework.boot.autoconfigure.web.servlet.JspTemplateAvailabilityProvider
一共124条默认配置,差不多涵盖了全部产品的配置,但是没有mybatis的配置(给自家产品Spring JPA让路),不过可以引入mybatis-springboot依赖解决这个问题
<dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.1</version> </dependency>
获取完默认配置后会调用 removeDuplicates去重、getExclusions和checkExcludedClasses去掉不想加载的配置以及filter方法留下有用的配置信息,最后交给spring IOC管理。
以上是关于SpringBoot自动配置源码的主要内容,如果未能解决你的问题,请参考以下文章
SpringBoot源码分析----SpringBoot自动配置
SpringBoot源码分析----SpringBoot自动配置原理
springboot自动配置源码解读以及jdbc和redis配置原理小点