经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » Spring Boot » 查看文章
Spring Boot自动注入的原理分析
来源:jb51  时间:2019/10/21 8:38:03  对本文有异议

前言

我们经常会被问到这么一个问题:SpringBoot相对于spring有哪些优势呢?其中有一条答案就是SpringBoot自动注入。那么自动注入的原理是什么呢?

我们进行如下分析。

1:首先我们分析项目的启动类时,发现都会加上@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 {

2:服务启动会扫描 org.springframework.boot.autoconfigure下的 META-INF/spring.factories 这个文件,这个文件中保存着springboot 启动时默认会自动注入的类,部分如下

  1. # Auto Configure
  2. 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.ElasticsearchRepositoriesAutoConfiguration,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.WebServicesAutoConfiguration

3:你是不是在其中发现了自己常用的redis,mysql等相关的类?没错,springboot会尝试加载这些类,我们以 org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration 这个类为例,进去看一下它的源码,部分示例如下

  1. @Configuration
  2. @ConditionalOnClass({ JedisConnection.class, RedisOperations.class, Jedis.class })
  3. @EnableConfigurationProperties(RedisProperties.class)
  4. public class RedisAutoConfiguration {
  5.  
  6. /**
  7. * Redis connection configuration.
  8. */
  9. @Configuration
  10. @ConditionalOnClass(GenericObjectPool.class)
  11. protected static class RedisConnectionConfiguration {
  12.  
  13. private final RedisProperties properties;
  14.  
  15. private final RedisSentinelConfiguration sentinelConfiguration;
  16.  
  17. private final RedisClusterConfiguration clusterConfiguration;
  18.  
  19. public RedisConnectionConfiguration(RedisProperties properties,
  20. ObjectProvider<RedisSentinelConfiguration> sentinelConfiguration,
  21. ObjectProvider<RedisClusterConfiguration> clusterConfiguration) {
  22. this.properties = properties;
  23. this.sentinelConfiguration = sentinelConfiguration.getIfAvailable();
  24. this.clusterConfiguration = clusterConfiguration.getIfAvailable();
  25. }
  26.  
  27. @Bean
  28. @ConditionalOnMissingBean(RedisConnectionFactory.class)
  29. public JedisConnectionFactory redisConnectionFactory()
  30. throws UnknownHostException {
  31. return applyProperties(createJedisConnectionFactory());
  32. }

我们能看到这个类上加了这个注解 @ConditionalOnClass({ JedisConnection.class, RedisOperations.class, Jedis.class }) 意思就是如果你的classpath中没有这些类的话,那么这个类就不能被加载,那么这些被依赖的类在哪出现呢?没错,就在我们在pom.xml中引入的依赖所对应的包里。

看到这里你因该就明白了,META-INF/spring.factories 文件中被列出来的那些类都会被springboot去尝试加载,但是有些模块我们没引入相关的依赖,那么这个类就会加载失败。即这个模块没有被成功加载。

4:我们通过上面的redis的自动加载类时,看到上面还有个 @EnableConfigurationProperties(RedisProperties.class) 注解,这个注解来注入关于redis的配置信息,这个信息都在 RedisProperties.class 中保存,我们看下 RedisProperties的源码

  1. @ConfigurationProperties(prefix = "spring.redis")
  2. public class RedisProperties {
  3.  
  4. /**
  5. * Database index used by the connection factory.
  6. */
  7. private int database = 0;
  8.  
  9. /**
  10. * Redis url, which will overrule host, port and password if set.
  11. */
  12. private String url;
  13.  
  14. /**
  15. * Redis server host.
  16. */
  17. private String host = "localhost";
  18.  
  19. /**
  20. * Login password of the redis server.
  21. */
  22. private String password;
  23.  
  24. /**
  25. * Redis server port.
  26. */
  27. private int port = 6379;
  28.  
  29. /**
  30. * Enable SSL.
  31. */
  32. private boolean ssl;
  33.  
  34. /**
  35. * Connection timeout in milliseconds.
  36. */
  37. private int timeout;
  38.  
  39. private Pool pool;
  40.  
  41. private Sentinel sentinel;
  42.  
  43. private Cluster cluster;
  44.  
  45. public int getDatabase() {
  46. return this.database;
  47. }
  48.  
  49. public void setDatabase(int database) {
  50. this.database = database;
  51. }
  52.  
  53. public String getUrl() {
  54. return this.url;
  55. }
  56.  
  57. public void setUrl(String url) {
  58. this.url = url;
  59. }
  60.  
  61. public String getHost() {
  62. return this.host;
  63. }
  64.  
  65. public void setHost(String host) {
  66. this.host = host;
  67. }
  68.  
  69. public String getPassword() {
  70. return this.password;
  71. }
  72.  
  73. public void setPassword(String password) {
  74. this.password = password;
  75. }
  76.  
  77. public int getPort() {
  78. return this.port;
  79. }
  80.  
  81. public void setPort(int port) {
  82. this.port = port;
  83. }
  84.  
  85. public boolean isSsl() {
  86. return this.ssl;
  87. }
  88.  
  89. public void setSsl(boolean ssl) {
  90. this.ssl = ssl;
  91. }
  92.  
  93. public void setTimeout(int timeout) {
  94. this.timeout = timeout;
  95. }
  96.  
  97. public int getTimeout() {
  98. return this.timeout;
  99. }
  100.  
  101. public Sentinel getSentinel() {
  102. return this.sentinel;
  103. }
  104.  
  105. public void setSentinel(Sentinel sentinel) {
  106. this.sentinel = sentinel;
  107. }
  108.  
  109. public Pool getPool() {
  110. return this.pool;
  111. }
  112.  
  113. public void setPool(Pool pool) {
  114. this.pool = pool;
  115. }
  116.  
  117. public Cluster getCluster() {
  118. return this.cluster;
  119. }
  120.  
  121. public void setCluster(Cluster cluster) {
  122. this.cluster = cluster;
  123. }
  124.  
  125. /**
  126. * Pool properties.
  127. */
  128. public static class Pool {
  129.  
  130. /**
  131. * Max number of "idle" connections in the pool. Use a negative value to indicate
  132. * an unlimited number of idle connections.
  133. */
  134. private int maxIdle = 8;
  135.  
  136. /**
  137. * Target for the minimum number of idle connections to maintain in the pool. This
  138. * setting only has an effect if it is positive.
  139. */
  140. private int minIdle = 0;
  141.  
  142. /**
  143. * Max number of connections that can be allocated by the pool at a given time.
  144. * Use a negative value for no limit.
  145. */
  146. private int maxActive = 8;
  147.  
  148. /**
  149. * Maximum amount of time (in milliseconds) a connection allocation should block
  150. * before throwing an exception when the pool is exhausted. Use a negative value
  151. * to block indefinitely.
  152. */
  153. private int maxWait = -1;
  154.  
  155. public int getMaxIdle() {
  156. return this.maxIdle;
  157. }
  158.  
  159. public void setMaxIdle(int maxIdle) {
  160. this.maxIdle = maxIdle;
  161. }
  162.  
  163. public int getMinIdle() {
  164. return this.minIdle;
  165. }
  166.  
  167. public void setMinIdle(int minIdle) {
  168. this.minIdle = minIdle;
  169. }
  170.  
  171. public int getMaxActive() {
  172. return this.maxActive;
  173. }
  174.  
  175. public void setMaxActive(int maxActive) {
  176. this.maxActive = maxActive;
  177. }
  178.  
  179. public int getMaxWait() {
  180. return this.maxWait;
  181. }
  182.  
  183. public void setMaxWait(int maxWait) {
  184. this.maxWait = maxWait;
  185. }
  186.  
  187. }
  188.  
  189. /**
  190. * Cluster properties.
  191. */
  192. public static class Cluster {
  193.  
  194. /**
  195. * Comma-separated list of "host:port" pairs to bootstrap from. This represents an
  196. * "initial" list of cluster nodes and is required to have at least one entry.
  197. */
  198. private List<String> nodes;
  199.  
  200. /**
  201. * Maximum number of redirects to follow when executing commands across the
  202. * cluster.
  203. */
  204. private Integer maxRedirects;
  205.  
  206. public List<String> getNodes() {
  207. return this.nodes;
  208. }
  209.  
  210. public void setNodes(List<String> nodes) {
  211. this.nodes = nodes;
  212. }
  213.  
  214. public Integer getMaxRedirects() {
  215. return this.maxRedirects;
  216. }
  217.  
  218. public void setMaxRedirects(Integer maxRedirects) {
  219. this.maxRedirects = maxRedirects;
  220. }
  221.  
  222. }
  223.  
  224. /**
  225. * Redis sentinel properties.
  226. */
  227. public static class Sentinel {
  228.  
  229. /**
  230. * Name of Redis server.
  231. */
  232. private String master;
  233.  
  234. /**
  235. * Comma-separated list of host:port pairs.
  236. */
  237. private String nodes;
  238.  
  239. public String getMaster() {
  240. return this.master;
  241. }
  242.  
  243. public void setMaster(String master) {
  244. this.master = master;
  245. }
  246.  
  247. public String getNodes() {
  248. return this.nodes;
  249. }
  250.  
  251. public void setNodes(String nodes) {
  252. this.nodes = nodes;
  253. }
  254.  
  255. }
  256.  
  257. }

发现里面的配置项基本都是有默认值的,通过上面的注解可以明白,如果配置文件中存在 spring.redis 开头的配置项,则使用配置文件中的,如果没有的话则使用文件中默认写死的配置。你是不是想到了springboot的另外一个优势:约定大于配置。

这里我们大概了解了SpringBoot自动配置的原理和流程,里面的那些细节我们不在分析。同理,对于那些第三方或者我们自己写的starter,springboot启动的时候会扫描starter的jar包下 META-INF/spring.factories 这个文件,解析内容并加载里面对用的类。

由此,我们总结出以下几点

  1:SpringBoot的自动配置是如何实现的

  2:有关的那些注解,如@EnableAutoConfiguration, @ConditionalOnClass, @Configuration等也是SpringBoot的核心注解,也值得我们了解其用法和原理。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对w3xue的支持。

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号