最近抽时间研究了一下springboot的自动配置,接下来简单介绍一下自动配置的源码及在springboot的项目里面怎么配置需要的各种属性。
本文以springboot 1.5.10为例。
首先看一下我们一个springboot启动类的代码:
1 @SpringBootApplication 2 @ServletComponentScan 3 public class WmLogApplication { 4 public static void main(String[] args) { 5 SpringApplication.run(WmLogApplication.class, args); 6 } 7 }
这里的注解@SpringBootApplication是关键,看一下源码:
1 @Target(ElementType.TYPE) 2 @Retention(RetentionPolicy.RUNTIME) 3 @Documented 4 @Inherited 5 @SpringBootConfiguration 6 @EnableAutoConfiguration 7 @ComponentScan(excludeFilters = { 8 @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), 9 @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) }) 10 public @interface SpringBootApplication {
。。。。。。。。 11 }
继续@EnableAutoConfiguration的源码:
1 @SuppressWarnings("deprecation") 2 @Target(ElementType.TYPE) 3 @Retention(RetentionPolicy.RUNTIME) 4 @Documented 5 @Inherited 6 @AutoConfigurationPackage 7 @Import(EnableAutoConfigurationImportSelector.class) 8 public @interface EnableAutoConfiguration {
通过@Import导入了EnableAutoConfigurationImportSelector,其源码:
1 @Deprecated 2 public class EnableAutoConfigurationImportSelector 3 extends AutoConfigurationImportSelector { 4 5 @Override 6 protected boolean isEnabled(AnnotationMetadata metadata) { 7 if (getClass().equals(EnableAutoConfigurationImportSelector.class)) { 8 return getEnvironment().getProperty( 9 EnableAutoConfiguration.ENABLED_OVERRIDE_PROPERTY, Boolean.class, 10 true); 11 } 12 return true; 13 } 14 15 }
继承自AutoConfigurationImportSelector ,在AutoConfigurationImportSelector 中:
1 @Override 2 public String[] selectImports(AnnotationMetadata annotationMetadata) { 3 if (!isEnabled(annotationMetadata)) { 4 return NO_IMPORTS; 5 } 6 try { 7 AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader 8 .loadMetadata(this.beanClassLoader); 9 AnnotationAttributes attributes = getAttributes(annotationMetadata); 10 List<String> configurations = getCandidateConfigurations(annotationMetadata, 11 attributes); 12 configurations = removeDuplicates(configurations); 13 configurations = sort(configurations, autoConfigurationMetadata); 14 Set<String> exclusions = getExclusions(annotationMetadata, attributes); 15 checkExcludedClasses(configurations, exclusions); 16 configurations.removeAll(exclusions); 17 configurations = filter(configurations, autoConfigurationMetadata); 18 fireAutoConfigurationImportEvents(configurations, exclusions); 19 return configurations.toArray(new String[configurations.size()]); 20 } 21 catch (IOException ex) { 22 throw new IllegalStateException(ex); 23 } 24 }
1 protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, 2 AnnotationAttributes attributes) { 3 List<String> configurations = SpringFactoriesLoader.loadFactoryNames( 4 getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader()); 5 Assert.notEmpty(configurations, 6 "No auto configuration classes found in META-INF/spring.factories. If you " 7 + "are using a custom packaging, make sure that file is correct."); 8 return configurations; 9 }
调用SpringFactoriesLoader.loadFactoryNames(),此方法是spring-core包里面的,其源码为:
1 public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) { 2 String factoryClassName = factoryClass.getName(); 3 try { 4 Enumeration<URL> urls = (classLoader != null ? classLoader.getResources(FACTORIES_RESOURCE_LOCATION) : 5 ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION)); 6 List<String> result = new ArrayList<String>(); 7 while (urls.hasMoreElements()) { 8 URL url = urls.nextElement(); 9 Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url)); 10 String factoryClassNames = properties.getProperty(factoryClassName); 11 result.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(factoryClassNames))); 12 } 13 return result; 14 } 15 catch (IOException ex) { 16 throw new IllegalArgumentException("Unable to load [" + factoryClass.getName() + 17 "] factories from location [" + FACTORIES_RESOURCE_LOCATION + "]", ex); 18 } 19 }
其中FACTORIES_RESOURCE_LOCATION的值为:
public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
查询到的META-INF/spring.factories文件是在spring-boot-autoconfigure-1.5.10.RELEASE.jar里面,看一下spring.factories:
1 # Initializers 2 org.springframework.context.ApplicationContextInitializer=\ 3 org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\ 4 org.springframework.boot.autoconfigure.logging.AutoConfigurationReportLoggingInitializer 5 6 # Application Listeners 7 org.springframework.context.ApplicationListener=\ 8 org.springframework.boot.autoconfigure.BackgroundPreinitializer 9 10 # Auto Configuration Import Listeners 11 org.springframework.boot.autoconfigure.AutoConfigurationImportListener=\ 12 org.springframework.boot.autoconfigure.condition.ConditionEvaluationReportAutoConfigurationImportListener 13 14 # Auto Configuration Import Filters 15 org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\ 16 org.springframework.boot.autoconfigure.condition.OnClassCondition 17 18 # Auto Configure 19 org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ 20 org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\ 21 org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\ 22 org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\ 23 org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\ 24 org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\ 25 org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\ 26 org.springframework.boot.autoconfigure.cloud.CloudAutoConfiguration,\ 27 org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\ 28 org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\ 29 org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\ 30 org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\ 31 org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,\ 32 org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,\ 33 org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration,\ 34 org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,\ 35 org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration,\ 36 org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration,\ 37 org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration,\ 38 org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration,\ 39 org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\ 40 org.springframework.boot.autoconfigure.data.ldap.LdapDataAutoConfiguration,\ 41 org.springframework.boot.autoconfigure.data.ldap.LdapRepositoriesAutoConfiguration,\ 42 org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration,\ 43 org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration,\ 44 org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration,\ 45 org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration,\ 46 org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration,\ 47 org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\ 48 org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration,\ 49 org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration,\ 50 org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration,\ 51 org.springframework.boot.autoconfigure.elasticsearch.jest.JestAutoConfiguration,\ 52 org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\ 53 org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,\ 54 org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration,\ 55 org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration,\ 56 org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration,\ 57 org.springframework.boot.autoconfigure.hazelcast.HazelcastJpaDependencyAutoConfiguration,\ 58 org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration,\ 59 org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration,\ 60 org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,\ 61 org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\ 62 org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration,\ 63 org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration,\ 64 org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration,\ 65 org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\ 66 org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration,\ 67 org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration,\ 68 org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration,\ 69 org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration,\ 70 org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration,\ 71 org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\ 72 org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,\ 73 org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration,\ 74 org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,\ 75 org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration,\ 76 org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration,\ 77 org.springframework.boot.autoconfigure.ldap.LdapAutoConfiguration,\ 78 org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration,\ 79 org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration,\ 80 org.springframework.boot.autoconfigure.mail.MailSenderValidatorAutoConfiguration,\ 81 org.springframework.boot.autoconfigure.mobile.DeviceResolverAutoConfiguration,\ 82 org.springframework.boot.autoconfigure.mobile.DeviceDelegatingViewResolverAutoConfiguration,\ 83 org.springframework.boot.autoconfigure.mobile.SitePreferenceAutoConfiguration,\ 84 org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration,\ 85 org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\ 86 org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,\ 87 org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\ 88 org.springframework.boot.autoconfigure.reactor.ReactorAutoConfiguration,\ 89 org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration,\ 90 org.springframework.boot.autoconfigure.security.SecurityFilterAutoConfiguration,\ 91 org.springframework.boot.autoconfigure.security.FallbackWebSecurityAutoConfiguration,\ 92 org.springframework.boot.autoconfigure.security.oauth2.OAuth2AutoConfiguration,\ 93 org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration,\ 94 org.springframework.boot.autoconfigure.session.SessionAutoConfiguration,\ 95 org.springframework.boot.autoconfigure.social.SocialWebAutoConfiguration,\ 96 org.springframework.boot.autoconfigure.social.FacebookAutoConfiguration,\ 97 org.springframework.boot.autoconfigure.social.LinkedInAutoConfiguration,\ 98 org.springframework.boot.autoconfigure.social.TwitterAutoConfiguration,\ 99 org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration,\ 100 org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\ 101 org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration,\ 102 org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration,\ 103 org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration,\ 104 org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration,\ 105 org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration,\ 106 org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration,\ 107 org.springframework.boot.autoconfigure.web.HttpEncodingAutoConfiguration,\ 108 org.springframework.boot.autoconfigure.web.HttpMessageConvertersAutoConfiguration,\ 109 org.springframework.boot.autoconfigure.web.MultipartAutoConfiguration,\ 110 org.springframework.boot.autoconfigure.web.ServerPropertiesAutoConfiguration,\ 111 org.springframework.boot.autoconfigure.web.WebClientAutoConfiguration,\ 112 org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration,\ 113 org.springframework.boot.autoconfigure.websocket.WebSocketAutoConfiguration,\ 114 org.springframework.boot.autoconfigure.websocket.WebSocketMessagingAutoConfiguration,\ 115 org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration 116 117 # Failure analyzers 118 org.springframework.boot.diagnostics.FailureAnalyzer=\ 119 org.springframework.boot.autoconfigure.diagnostics.analyzer.NoSuchBeanDefinitionFailureAnalyzer,\ 120 org.springframework.boot.autoconfigure.jdbc.DataSourceBeanCreationFailureAnalyzer,\ 121 org.springframework.boot.autoconfigure.jdbc.HikariDriverConfigurationFailureAnalyzer 122 123 # Template availability providers 124 org.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider=\ 125 org.springframework.boot.autoconfigure.freemarker.FreeMarkerTemplateAvailabilityProvider,\ 126 org.springframework.boot.autoconfigure.mustache.MustacheTemplateAvailabilityProvider,\ 127 org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAvailabilityProvider,\ 128 org.springframework.boot.autoconfigure.thymeleaf.ThymeleafTemplateAvailabilityProvider,\ 129 org.springframework.boot.autoconfigure.web.JspTemplateAvailabilityProvider
可以看到一系列自动配置的列表,springboot启动时会自动加载。每一个Configuration都会有自己的默认配置文件,我们这里就用常用的数据库连接的配置为例,
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
1 @Configuration 2 @ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class }) 3 @EnableConfigurationProperties(DataSourceProperties.class) 4 @Import({ Registrar.class, DataSourcePoolMetadataProvidersConfiguration.class }) 5 public class DataSourceAutoConfiguration { 6 7 private static final Log logger = LogFactory 8 .getLog(DataSourceAutoConfiguration.class); 9 10 @Bean 11 @ConditionalOnMissingBean 12 public DataSourceInitializer dataSourceInitializer(DataSourceProperties properties, 13 ApplicationContext applicationContext) { 14 return new DataSourceInitializer(properties, applicationContext); 15 }
DataSourceProperties里面的属性:
1 @ConfigurationProperties(prefix = "spring.datasource") 2 public class DataSourceProperties 3 implements BeanClassLoaderAware, EnvironmentAware, InitializingBean { 4 5 private ClassLoader classLoader; 6 7 private Environment environment; 8 9 /** 10 * Name of the datasource. 11 */ 12 private String name = "testdb"; 13 14 /** 15 * Generate a random datasource name. 16 */ 17 private boolean generateUniqueName; 18 19 /** 20 * Fully qualified name of the connection pool implementation to use. By default, it 21 * is auto-detected from the classpath. 22 */ 23 private Class<? extends DataSource> type; 24 25 /** 26 * Fully qualified name of the JDBC driver. Auto-detected based on the URL by default. 27 */ 28 private String driverClassName; 29 30 /** 31 * JDBC url of the database. 32 */ 33 private String url; 34 35 /** 36 * Login user of the database. 37 */ 38 private String username; 39 40 /** 41 * Login password of the database. 42 */ 43 private String password;
再看一下我们自己项目里面的application.properties:
spring.datasource.url=jdbc:mysql://localhost:3306/test spring.datasource.type=com.zaxxer.hikari.HikariDataSource spring.datasource.username=root spring.datasource.password= spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.hikari.minimum-idle=5
spring.datasource.hikari.maximum-pool-size=15
spring.datasource.hikari.idle-timeout=30000
spring.datasource.hikari.max-lifetime=1800000
spring.datasource.hikari.connection-timeout=30000
因为我们使用了hikari连接池,所以多配置了一些属性。
在DataSourceConfiguration 的配置中,我们可以看到连接池的支持:
1 abstract class DataSourceConfiguration { 2 3 @SuppressWarnings("unchecked") 4 protected <T> T createDataSource(DataSourceProperties properties, 5 Class<? extends DataSource> type) { 6 return (T) properties.initializeDataSourceBuilder().type(type).build(); 7 } 8 9 /** 10 * Tomcat Pool DataSource configuration. 11 */ 12 @ConditionalOnClass(org.apache.tomcat.jdbc.pool.DataSource.class) 13 @ConditionalOnProperty(name = "spring.datasource.type", havingValue = "org.apache.tomcat.jdbc.pool.DataSource", matchIfMissing = true) 14 static class Tomcat extends DataSourceConfiguration { 15 16 @Bean 17 @ConfigurationProperties(prefix = "spring.datasource.tomcat") 18 public org.apache.tomcat.jdbc.pool.DataSource dataSource( 19 DataSourceProperties properties) { 20 org.apache.tomcat.jdbc.pool.DataSource dataSource = createDataSource( 21 properties, org.apache.tomcat.jdbc.pool.DataSource.class); 22 DatabaseDriver databaseDriver = DatabaseDriver 23 .fromJdbcUrl(properties.determineUrl()); 24 String validationQuery = databaseDriver.getValidationQuery(); 25 if (validationQuery != null) { 26 dataSource.setTestOnBorrow(true); 27 dataSource.setValidationQuery(validationQuery); 28 } 29 return dataSource; 30 } 31 32 } 33 34 /** 35 * Hikari DataSource configuration. 36 */ 37 @ConditionalOnClass(HikariDataSource.class) 38 @ConditionalOnProperty(name = "spring.datasource.type", havingValue = "com.zaxxer.hikari.HikariDataSource", matchIfMissing = true) 39 static class Hikari extends DataSourceConfiguration { 40 41 @Bean 42 @ConfigurationProperties(prefix = "spring.datasource.hikari") 43 public HikariDataSource dataSource(DataSourceProperties properties) { 44 return createDataSource(properties, HikariDataSource.class); 45 } 46 47 } 48 49 /** 50 * DBCP DataSource configuration. 51 * 52 * @deprecated as of 1.5 in favor of DBCP2 53 */ 54 @ConditionalOnClass(org.apache.commons.dbcp.BasicDataSource.class) 55 @ConditionalOnProperty(name = "spring.datasource.type", havingValue = "org.apache.commons.dbcp.BasicDataSource", matchIfMissing = true) 56 @Deprecated 57 static class Dbcp extends DataSourceConfiguration { 58 59 @Bean 60 @ConfigurationProperties(prefix = "spring.datasource.dbcp") 61 public org.apache.commons.dbcp.BasicDataSource dataSource( 62 DataSourceProperties properties) { 63 org.apache.commons.dbcp.BasicDataSource dataSource = createDataSource( 64 properties, org.apache.commons.dbcp.BasicDataSource.class); 65 DatabaseDriver databaseDriver = DatabaseDriver 66 .fromJdbcUrl(properties.determineUrl()); 67 String validationQuery = databaseDriver.getValidationQuery(); 68 if (validationQuery != null) { 69 dataSource.setTestOnBorrow(true); 70 dataSource.setValidationQuery(validationQuery); 71 } 72 return dataSource; 73 } 74 75 }
由spring.datasource.type指定类型,支持hikari,dbcp,dbcp2等。
如果在使用时自己的项目中不清楚具体要配置哪些属性,可以查询相关的properties(如DataSourceProperties),有些必须要配置的属性没有配置的话,启动时可能会报错。
其他的配置如jedis,jpa等都可以按照上述的方式进行查阅,默认的属性在spring-boot-autoconfigure-1.5.10.RELEASE.jar下的META-INF/spring-configuration-metadata.json文件里面。