最近抽时间研究了一下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文件里面。

 

posted on 2019-01-14 15:47  jameszheng  阅读(713)  评论(0编辑  收藏  举报