深入了解SpringBoot的自动配置原理

电子说

1.2w人已加入

描述

通过这篇文章我们来深入了解SpringBoot的自动配置原理,并分析SpringBoot是如何神不知,鬼不觉的帮我们做了那么多的事情,让我们只需要关心业务逻辑开发就可以了。

创建一个SpringBoot项目

SpringBoot

首先还是得从主程序MainApplication开始

SpringBoot

里面有一个main方法,用来启动SpringBoot应用,但是最重要的还是@SpringBootApplication这个核心注解

SpringBoot

@SpringBootApplication注解是一个复合注解,他的作用就相当于下面的三个注解

SpringBoot

@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan

接下来我们挨个分析这些注解的功能

第一个注解是@SpringBootConfiguration

SpringBoot

这个注解我们点进去会发现

SpringBoot

他就是一个@Configuration,那这个注解的作用很简单,他就代表当前类是一个配置类,而@SpringBootConfiguration只不过是一个核心的配置类,仅此而已。

第二个注解@ComponentScan

SpringBoot

这个注解也很简单,他其实就是一个包扫描,给我们指定要扫描哪些东西,他其中有两个自定义扫描器,就是上面的两个classes,这个和Spring中的注解是一样的,在这里研究这两个的意义也不是很大。

我们来看第三个注解@EnableAutoConfiguration,也是最重要的一个

SpringBoot

这个注解,点进去会发现,他也是一个复合注解

SpringBoot

第一个注解@AutoConfigurationPackage,翻译过来就是自动配置包,指定了默认的包规则,我们再点进去,来看

SpringBoot

这个@Import注解的作用是给容器中导入一个组件。

也就是说在这里其实是利用Registrar给容器中导入了一系列组件,并且指定了将MainApplication所在包下的所有组件导入进来。这个其实也不是我们要研究的重点

再来看@EnableAutoConfiguration中的第二个注解

@Import({AutoConfigurationImportSelector.class})

我们点进去,AutoConfigurationImportSelector中有一个方法叫做

selectImports方法

SpringBoot

这个方法的作用就是我们到底要给容器导入哪些组件,方法的返回值是一个String[ ]数组。

得到所有组件是通过 getAutoConfigurationEntry方法,调用这个方法以后会得到

SpringBoot

autoConfigurationEntry的对象

SpringBoot

通过autoConfigurationEntry得到所有的配置,然后转成String数组返回出去。

SpringBoot

autoConfigurationEntry.getConfigurations( )

所以,在这一块儿我们只要研究清楚getAutoConfigurationEntry(annotationMetadata)这个方法就可以了。

getAutoConfigurationEntry(annotationMetadata)这个方法的作用是给容器批量导入一些组件,通过断点调试的方式,来研究这个方法具体导入了哪些组件

在这个方法的实现上打一个断点,以debug模式运行,进来以后F8 step over往下放行,其中有一个方法叫做getCandidateConfigurations(annotationMetadata,attributes);

SpringBoot

这个方法的作用是获取所有候选的配置

调用这个方法会得到一个configurations对象,再往下放行,我们会看到这个configurations对象会进行删除重复的操作,得到排除的操作和过滤的一些操作,最后进行一个封装,给他返回出去

SpringBoot这个configurations中有124个组件,他们是默认要导入到容器中的。

SpringBoot

为了弄清楚这124个组件是以什么样的规则导入这124个组件,接下来重新以debug方式运行,getCandidateConfigurations(annotationMetadata,attributes)方法,F7 step into 进来

SpringBoot

可以看到,他其实是通过SpringFactoryLoader使用Spring的这些工厂加载器,来加载工厂名称,选择LoadFactoryNames,点进去,可以看到返回的是loadSpringFactories

SpringBoot

看这个方法的实现,其实最终就是通过这个方法来进行加载,最终得到一个Map集合

SpringBoot

所以我们只要搞明白loadSpringFactories这个方法就可以了,我们在这儿打一个断点,然后重新启动

SpringBoot

F8 放行,可以看到第一个result 是初始的为null ,

SpringBoot

往下放行,可以看到classLoader.getResources()的方法

他相当于是从META-INF/spring.factories位置来获取资源文件,并且这个位置他默认会扫描当前系统里面所有META-INF/spring.factories位置的文件

SpringBoot

我们看spring-boot-autoconfigure-2.2.0.RELEASE.jar

SpringBoot

那这个里面呢,最核心的东西就出现了

往下可以看到,从22行到145行,就是要加载的之前我们说的124个组件,他其实是在文件当中写死的,我们发现@EnableAutoConfiguration要加载哪些类,在这儿都有配置,并且每一个都有一个换行符,都是一个全类名,都是叫XXXXAutoConfiguration,就是什么东西的自动配置。

那SpringBoot兼容的全场景自动配置,他全在这儿列举过来了。

# 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

我们把这124个组件全部拿过来,但是这个时候问题又来了,要把这124个组件全部加载进来,但我们的SpringBoot容器里面可能都没有这么多的组件,所以,在这个时候就涉及到了SpringBoot中的按需开启自动配置项。

打开下面的

SpringBoot

比如消息队列,AOP切面这些包,那么这些功能,能不能实现呢?

带着这个疑问,点开消息队列的类,来看

SpringBoot

还有AOP切面的类

SpringBoot

可以发现,这些功能并没有实现,那没有实现的原因其实也很简单

SpringBoot

@ ConditionalOnClass这个注解的作用就是按条件,说白了就是我们整个的类路径存在这个类下面的一堆配置才生效,那么什么时候才会有这个类呢?其实就是你只有导入了aop相关的包,比如我们这边需要导入的(org.aspectj.weaver.Advice)

SpringBoot

导入这个包以后才会有上面的那些类,有了这些类以后这些组件才会生效。

总结 :刚开始我们看到他一股脑加载了所有的组件,但是呢,最终得益于SpringBoot的按需加载的注解,就是上面我们说的条件装配@ConditionalOnClass,所以好多东西,并不能完全开启。这个就是SpringBoot自动配置的核心,启动时加载所有,最终按照条件进行装配。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分