SpringBoot自動(dòng)配置原理

1. 自動(dòng)導(dǎo)入包的原理

我們都知道,SpringBoot會(huì)把主程序類所在包下的所有組件加入到容器中,這個(gè)是怎么實(shí)現(xiàn)的呢?

  1. 首先查看一下@SpringBootApplication這個(gè)注解

    @SpringBootConfiguration
    @EnableAutoConfiguration
    @ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
         @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
    

    可以看到這個(gè)注解是由三個(gè)子注解構(gòu)成的

    1. @SpringBootConfiguration

      @Configuration
      public @interface SpringBootConfiguration {}
      

      這個(gè)注解的核心就是一個(gè)Spring底層的@Configuration注解,表示被注解的是一個(gè)配置類

    2. @ComponentScan

      該注解就是用來掃描指定包下的用@Component注解的類的

    3. @EnableAutoConfiguration

      該注解才是實(shí)現(xiàn)自動(dòng)導(dǎo)入包的核心!??!

      @AutoConfigurationPackage
      @Import(AutoConfigurationImportSelector.class)
      public @interface EnableAutoConfiguration {}
      
      • 關(guān)鍵是看這個(gè)注解 -- @AutoConfigurationPackage

        @Import(AutoConfigurationPackages.Registrar.class)
        public @interface AutoConfigurationPackage {}
        

        這個(gè)注解使用了@Import的高級(jí)用法,可以批量導(dǎo)入組件,我們點(diǎn)進(jìn)Registrar看看

        static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
        
            @Override
            public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
                register(registry, new PackageImports(metadata).getPackageNames().toArray(new String[0]));
            }
        
            @Override
            public Set<Object> determineImports(AnnotationMetadata metadata) {
                return Collections.singleton(new PackageImports(metadata));
            }
        
        }
        

        register(registry, new PackageImports(metadata).getPackageNames().toArray(new String[0]));

        這句代碼就是核心!new PackageImports(metadata).getPackageNames()這個(gè)的返回結(jié)果就是SpringBoot主程序類所在包的路徑,比如這里我們把主程序類放在了com.plasticine.boot這個(gè)包下,那么這段代碼返回的結(jié)果就是com.plasticine.boot,然后就可以把這個(gè)包下的組件都批量導(dǎo)入了!

      • @Import(AutoConfigurationImportSelector.class)

        重點(diǎn)是看AutoConfigurationImportSelector這個(gè)類里面是做了什么從而實(shí)現(xiàn)了自動(dòng)裝配,點(diǎn)進(jìn)去后可以看到有一個(gè)方法selectImports

        @Override
        public String[] selectImports(AnnotationMetadata annotationMetadata) {
            if (!isEnabled(annotationMetadata)) {
                return NO_IMPORTS;
            }
            AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);
            return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
        }
        

        該方法的意思大概就是根據(jù)注解元信息獲取到自動(dòng)配置的入口,這個(gè)入口就是用@Configuration注解標(biāo)記過的類構(gòu)成的集合,然后從這些集合中得到所有的配置信息后轉(zhuǎn)成字符串?dāng)?shù)組返回,后面就可以根據(jù)返回的字符串?dāng)?shù)組中的有哪些全類名去進(jìn)行自動(dòng)裝配了

        所以核心就在于getAutoConfigurationEntry(annotationMetadata)這個(gè)方法,這個(gè)方法中有一步是獲取所有要導(dǎo)入到容器中的配置類的,也就是

        List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
        
        configurations變量中的內(nèi)容,即所有的自動(dòng)裝配類

        點(diǎn)進(jìn)getCandidateConfigurations方法查看

        List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
                        getBeanClassLoader());
        

        可以看到配置類是從Spring的工廠中加載來的,再點(diǎn)進(jìn)loadFactoryNames這個(gè)方法查看

        return (List)loadSpringFactories(classLoaderToUse).getOrDefault(factoryTypeName, Collections.emptyList());
        

        這個(gè)方法最終返回是通過調(diào)用loadSpringFactories這個(gè)方法,那么再點(diǎn)進(jìn)這個(gè)方法看看

        package org.springframework.core.io.support;
        Enumeration urls = classLoader.getResources("META-INF/spring.factories");
        

        終于看到有這樣一行和配置相關(guān)的了,Spring就是從這里去加載要使用的配置類的,我們可以找到springboot的這個(gè)包org.springframework.core.io.support,也就是spring-boot-autoconfigure-2.5.4.jar,在這個(gè)包的META-INF中就可以看到spring.factories這個(gè)文件,打開后看到有一行注釋是Auto Configure

        # 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.context.ConfigurationPropertiesAutoConfiguration,\
        org.springframework.boot.autoconfigure.context.LifecycleAutoConfiguration,\
        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.ElasticsearchDataAutoConfiguration,\
        org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration,\
        org.springframework.boot.autoconfigure.data.elasticsearch.ReactiveElasticsearchRepositoriesAutoConfiguration,\
        org.springframework.boot.autoconfigure.data.elasticsearch.ReactiveElasticsearchRestClientAutoConfiguration,\
        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.Neo4jReactiveDataAutoConfiguration,\
        org.springframework.boot.autoconfigure.data.neo4j.Neo4jReactiveRepositoriesAutoConfiguration,\
        org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration,\
        org.springframework.boot.autoconfigure.data.r2dbc.R2dbcDataAutoConfiguration,\
        org.springframework.boot.autoconfigure.data.r2dbc.R2dbcRepositoriesAutoConfiguration,\
        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.ElasticsearchRestClientAutoConfiguration,\
        org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\
        org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\
        org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,\
        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.jersey.JerseyAutoConfiguration,\
        org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,\
        org.springframework.boot.autoconfigure.jsonb.JsonbAutoConfiguration,\
        org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration,\
        org.springframework.boot.autoconfigure.availability.ApplicationAvailabilityAutoConfiguration,\
        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.neo4j.Neo4jAutoConfiguration,\
        org.springframework.boot.autoconfigure.netty.NettyAutoConfiguration,\
        org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
        org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration,\
        org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration,\
        org.springframework.boot.autoconfigure.r2dbc.R2dbcTransactionManagerAutoConfiguration,\
        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.sql.init.SqlInitializationAutoConfiguration,\
        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
        

        正好就是這里面的131個(gè)配置類,雖然springboot把這么多配置類都加載進(jìn)容器中了,但是項(xiàng)目中并不是每一個(gè)都用到了,所以springboot有一個(gè)按需開啟的功能,啟動(dòng)springboot的時(shí)候會(huì)默認(rèn)加載所有的自動(dòng)配置類,但是只有我們用到了的配置項(xiàng)才會(huì)真正的自動(dòng)裝配到容器中,按需配置

        • 這句話什么意思呢?隨便舉一個(gè)例子吧

          就拿aop為例,如果項(xiàng)目中沒有用到aop,那么雖然配置項(xiàng)中有aop這一項(xiàng)

          org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
          

          但是當(dāng)我們點(diǎn)進(jìn)去AopAutoConfiguration這個(gè)類看一看就會(huì)發(fā)現(xiàn)

          public class AopAutoConfiguration {
          
            @Configuration(proxyBeanMethods = false)
            @ConditionalOnClass(Advice.class)
            static class AspectJAutoProxyingConfiguration {
                  ...
              }
          

          這個(gè)類被@ConditionalOnClass注解了,也就是說,容器中有Advice這個(gè)類的時(shí)候,才會(huì)自動(dòng)裝配aop,而Advice就是import org.aspectj.weaver.Advice;,所以如果我們項(xiàng)目中沒有在pom.xml中引入aspectj依賴的話,Advice這個(gè)類是無法導(dǎo)入的,那么aop的自動(dòng)裝配也就不會(huì)發(fā)生

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容