SpringBoot02-自动配置原理

自动配置原理 

原理

  1. SpringBoot启动时加载主配置类, 开启了自动配置功能@EnableAutoConfiguration.
  2. @EnableAutoConfiguration作用
    1. 利用@Import({AutoConfigurationImportSelector.class})给容器导入了一些组件.
    2. 查看selectImports()方法
      List<String> configurations = getCandidateConfigurations(annotationMetadata,attributes); //获取了候选的配置
    3. getCandidateConfigurations()中
      List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());
    4. loadFactoryNames()中
      try {
                  //扫描了所有jar包类路径下: META-INF/spring.factories
                  Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories");
                  ArrayList result = new ArrayList();
                  //把扫描到的文件包装成properties对象
                  while(urls.hasMoreElements()) {
                      URL url = (URL)urls.nextElement();
                      Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url));
                      String factoryClassNames = properties.getProperty(factoryClassName);
                      //从properties中获取到EnableAutoConfiguration.class类(类名)对应的值,然后把他们添加在容器 中
                      result.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(factoryClassNames)));
                  }
      
                  return result;
              } 
      • 将类路径下 META-INF/spring.factories 里面配置的所有EnableAutoConfiguration的值加入到了容器中
        # 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.CassandraRepositoriesAutoConfiguration ,\
        org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,\
        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.ElasticsearchRepositoriesAutoConfi guration,\
        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.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.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.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.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.flyway.FlywayAutoConfiguration,\
        org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,\
        org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration,\ org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,\
        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.mobile.DeviceResolverAutoConfiguration,\
        org.springframework.boot.autoconfigure.mobile.DeviceDelegatingViewResolverAutoConfiguration, \
        org.springframework.boot.autoconfigure.mobile.SitePreferenceAutoConfiguration,\
        org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration,\
        org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\ org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,\ org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\ org.springframework.boot.autoconfigure.reactor.ReactorAutoConfiguration,\
        org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration,\
        org.springframework.boot.autoconfigure.security.SecurityFilterAutoConfiguration,\
        org.springframework.boot.autoconfigure.security.FallbackWebSecurityAutoConfiguration,\
        org.springframework.boot.autoconfigure.security.oauth2.OAuth2AutoConfiguration,\
        org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration,\
        org.springframework.boot.autoconfigure.session.SessionAutoConfiguration,\
        org.springframework.boot.autoconfigure.social.SocialWebAutoConfiguration,\
        org.springframework.boot.autoconfigure.social.FacebookAutoConfiguration,\
        org.springframework.boot.autoconfigure.social.LinkedInAutoConfiguration,\
        org.springframework.boot.autoconfigure.social.TwitterAutoConfiguration,\
        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.DispatcherServletAutoConfiguration,\
        org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration,\
        org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration,\
        org.springframework.boot.autoconfigure.web.HttpEncodingAutoConfiguration,\
        org.springframework.boot.autoconfigure.web.HttpMessageConvertersAutoConfiguration,\
        org.springframework.boot.autoconfigure.web.MultipartAutoConfiguration,\
        org.springframework.boot.autoconfigure.web.ServerPropertiesAutoConfiguration,\
        org.springframework.boot.autoconfigure.web.WebClientAutoConfiguration,\
        org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration,\
        org.springframework.boot.autoconfigure.websocket.WebSocketAutoConfiguration,\
        org.springframework.boot.autoconfigure.websocket.WebSocketMessagingAutoConfiguration,\
        org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguratio
      • 每一个这样的xxxAutoConfiguration类都是容器中的一个组件, 都加入到容器中, 用他们来做自动配置.
  3. 每个自动配置类进入容器中后, 进行自动配置功能.
  4. 以HttpEncodingAutoConfiguration为例解释自动配置原理
    @Configuration //表示这是一个配置类
    /*
     * 启动指定类的 ConfigurationProperties功能;将配置文件中对应的值和HttpEncodingProperties绑定起来;
     * 并把 HttpEncodingProperties加入到ioc容器中.
    */
    @EnableConfigurationProperties(HttpEncodingProperties.class)
    @ConditionalOnWebApplication //判断当前应用是否是web应用, 如果是, 当前配置类生效 
    /*
     * 判断当前项目有没有这个类
     * CharacterEncodingFilter: SpringMVC中进行乱码解决的过滤器
    */
    @ConditionalOnClass(CharacterEncodingFilter.class)
    /*
     * 判断配置文件中是否存在某个配置
    */
    @ConditionalOnProperty(prefix = "spring.http.encoding", value = "enabled", matchIfMissing = true) //即使我们配置文件中不配置pring.http.encoding.enabled=true,也是默认生效的;
    public class HttpEncodingAutoConfiguration {
    
        private final HttpEncodingProperties properties;
    
        //只有一个有参构造器的情况下,参数的值就会从容器中拿
        public HttpEncodingAutoConfiguration(HttpEncodingProperties properties) {
            this.properties = properties;
        }
    
        //给容器中添加一个组件,这个组件的某些值需要从properties中获取
        @Bean
        @ConditionalOnMissingBean(CharacterEncodingFilter.class) //判断容器没有这个组件
        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;
        }
    1. 根据当前不同的条件判断, 觉得这个配置类是否生效.
    2. 一旦该配置类生效, 就会给容器添加各种组件, 这些组件的属性是从对应的properties类中获取的,这些类里面的每一个属性又是和配置文件绑定的.
  5. 所有在配置文件中能配置的属性都是在xxxxProperties类中封装的, 配置文件能配置什么就可以参照某个功能对应的这个属性类.

    @ConfigurationProperties(prefix = "spring.http.encoding")
    public class HttpEncodingProperties {
    
        public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
    
        private Charset charset = DEFAULT_CHARSET;
    
        private Boolean force;
    
        private Boolean forceRequest;
    
        private Boolean forceResponse;
    
        ......
  6. 总结
    1. SpringBoot启动时会加载大量的自动配置类.
    2. 我们看我们需要的功能有没有被SpringBoot写入默认的自动配置类.
    3. 我们再来看这个自动配置类中到底配置了哪些组件(只要我们要用的组件有, 我们就不需要再来配置了)
    4. 给容器中自动配置类添加组件的时候, 会从properties类中获取某些属性, 我们就可以在配置文件中指定这些属性的值.

细节

  1. @Conditional派生注解
  2.  自动配置类只有在一定条件下才能生效
    1. 在application.properties/yml中启用debug=true属性, 来让控制台打印自动配置报告, 这样就可以很方便的知道哪些自动配置类生效.
    2.  

       

 

posted @ 2020-05-11 21:04  yellowstreak  阅读(235)  评论(0编辑  收藏  举报