Spring Boot自动装配

分手后的思念是犯贱 2022-03-22 14:28 425阅读 0赞

Spring Boot自动装配

题记

在日常的开发过程中Spring Boot自动装配的特性给我们开发减少了很多重复性的工作,具体时如果实现自动装配的呢,我们会在下一篇文章做详细的分析,以及用源码解析跟实战方式带大家了解Spring Boot “自动化”的原因,我们将透过现象去发现本质。

  1. Spring Boot介绍:
  2. Create stand-alone Spring applications
  3. -- 创建一个独立的Spring应用
  4. Embed Tomcat, Jetty or Undertow directly (no need to deploy WAR files)
  5. -- 嵌入式的web服务器TomcatJettyUndertow(无需部署 war 文件)
  6. Provide opinionated 'starter' dependencies to simplify your build configuration
  7. -- 提供建议的 "启动" 依赖关系, 以简化生成配置
  8. Automatically configure Spring and 3rd party libraries whenever possible
  9. -- 尽可能自动配置 spring 和第三方库
  10. Provide production-ready features such as metrics, health checks and externalized configuration
  11. -- 具备为生产准备的特性,如指标、运行状况检查和外部化配置
  12. Absolutely no code generation and no requirement for XML configuration
  13. -- 尽可能的无需代码生成并且无XML配置

话不多说,开始进入本次分享的主题,在Spring Boot@EnableAutoConfiguration的使用显得十分普遍,使用越多遇到的问题可能也就越多。为什么笔者会这样说呢,因为在程序开发的过程中,引入新技术一般会有两个原因:

  1. 第一:更便捷,能明显提高开发效率,否则一般的团队很少会主动尝试新事物。毕竟新的就意味着有风险
  2. 第二:对程序有显著地提升(此处是指可以是性能,也可以是健壮性,可用性,并发处理能力等等)

注解分析


























































注解名称 作用
@Component 基础注解(元注解),可被嵌套
@Configuration 声明定义Bean,嵌套了@Component
@Import 导入类(如AutoConfigurationImportSelector.class)
@ImportResource 导入文件(“classpath:/com/acme/database-config.xml”)
@AutoConfigureAfter 条件注解控制相对顺序(在条件注入之后注入),Order实现绝对顺序控制
@ConditionalOnClass 当类存在时装配
@ConditionalOnMissingClass 当类不存在时装配
@EnableAutoConfiguration 使用该注解实现自动装配
@SpringBootConfiguration 包含@Configuration,启动类的标注
@PropertySource properties文件加载
@ConditionalOnSystemProperty properties文件中存在满足条件的属性时装配
@EnableConfigurationProperties 是带有@ConfigurationProperties注解的类生效

在实际的使用中h还会有很多注解的定义与使用,在我们的日常开发中需要根据实际情况去选择使用。

自动装配

由于Spring Boot自动装配的特性,所以在jar引入后,我们会得到Spring容器为我们量身定做的实例,即我们所谓的Bean,这个过程中当然不可或缺的有RestTemplate,使用JDBC或者MyBatis等时会有JdbcTemplate生成。

  1. //在Spring Boot中通过@EnableAutoConfiguration实现自动装配对象的选择
  2. @Target(ElementType.TYPE)
  3. @Retention(RetentionPolicy.RUNTIME)
  4. @Documented
  5. @Inherited
  6. @AutoConfigurationPackage
  7. //具体选择器实现
  8. @Import(AutoConfigurationImportSelector.class)
  9. public @interface EnableAutoConfiguration {
  10. ...
  11. }

该示例即为RestTemplate自动注入,包含条件注解:在HttpMessageConvertersAutoConfiguration自动注入之后;在RestTemplate.class存在时注入

  1. @Configuration
  2. @AutoConfigureAfter(HttpMessageConvertersAutoConfiguration.class)
  3. @ConditionalOnClass(RestTemplate.class)
  4. public class RestTemplateAutoConfiguration {
  5. ...
  6. @Bean
  7. }

该示例即为JdbcTemplate自动注入,包含条件注解:在DataSourceAutoConfiguration自动注入之后;在JdbcTemplate.classDataSource.class并且DataSource为单例时,存在时注入

  1. @Configuration
  2. @ConditionalOnClass({ DataSource.class, JdbcTemplate.class })
  3. @ConditionalOnSingleCandidate(DataSource.class)
  4. @AutoConfigureAfter(DataSourceAutoConfiguration.class)
  5. @EnableConfigurationProperties(JdbcProperties.class)
  6. public class JdbcTemplateAutoConfiguration {
  7. @Bean
  8. @Bean
  9. @Primary
  10. @ConditionalOnMissingBean(JdbcOperations.class)
  11. public JdbcTemplate jdbcTemplate() {
  12. ...
  13. }
  14. }

RestTemplateAutoConfigurationJdbcTemplateAutoConfiguration在spring-boot-autoconfiguration包下的META-INF/spring.factories中声明

  1. # Auto Configure
  2. org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  3. org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration,\
  4. org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration

而后被AutoConfigurationImportSelector选择加载,该类实现了ImportSelector接口,具体加载的位置在invokeBeanFactoryPostProcessors(beanFactory);注册的时候,实现Bean的注册;而在Bean注册之前会有BeanClassResourceEnvironment等的属性注入;Ordered接口主要是确定加载的顺序。

  1. public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
  2. ...
  3. @Override
  4. public String[] selectImports(AnnotationMetadata annotationMetadata) {
  5. if (!isEnabled(annotationMetadata)) {
  6. return NO_IMPORTS;
  7. }
  8. AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
  9. .loadMetadata(this.beanClassLoader);
  10. AnnotationAttributes attributes = getAttributes(annotationMetadata);
  11. List<String> configurations = getCandidateConfigurations(annotationMetadata,
  12. attributes);
  13. configurations = removeDuplicates(configurations);
  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 StringUtils.toStringArray(configurations);
  20. }
  21. }

如上所述可以实现,RestTemplateAutoConfigurationJdbcTemplateAutoConfiguration的自动注入得以实现。

可自动装配列表

  1. # Auto Configure
  2. org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  3. org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
  4. org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
  5. org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
  6. org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
  7. org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
  8. org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
  9. org.springframework.boot.autoconfigure.cloud.CloudAutoConfiguration,\
  10. org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
  11. org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
  12. org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\
  13. org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\
  14. org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,\
  15. org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,\
  16. org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveDataAutoConfiguration,\
  17. org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveRepositoriesAutoConfiguration,\
  18. org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration,\
  19. org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,\
  20. org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveDataAutoConfiguration,\
  21. org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveRepositoriesAutoConfiguration,\
  22. org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration,\
  23. org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration,\
  24. org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration,\
  25. org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration,\
  26. org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\
  27. org.springframework.boot.autoconfigure.data.ldap.LdapDataAutoConfiguration,\
  28. org.springframework.boot.autoconfigure.data.ldap.LdapRepositoriesAutoConfiguration,\
  29. org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration,\
  30. org.springframework.boot.autoconfigure.data.mongo.MongoReactiveDataAutoConfiguration,\
  31. org.springframework.boot.autoconfigure.data.mongo.MongoReactiveRepositoriesAutoConfiguration,\
  32. org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration,\
  33. org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration,\
  34. org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration,\
  35. org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration,\
  36. org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\
  37. org.springframework.boot.autoconfigure.data.redis.RedisReactiveAutoConfiguration,\
  38. org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration,\
  39. org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration,\
  40. org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration,\
  41. org.springframework.boot.autoconfigure.elasticsearch.jest.JestAutoConfiguration,\
  42. org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\
  43. org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\
  44. org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,\
  45. org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration,\
  46. org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration,\
  47. org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration,\
  48. org.springframework.boot.autoconfigure.hazelcast.HazelcastJpaDependencyAutoConfiguration,\
  49. org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration,\
  50. org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration,\
  51. org.springframework.boot.autoconfigure.influx.InfluxDbAutoConfiguration,\
  52. org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration,\
  53. org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration,\
  54. org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,\
  55. org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
  56. org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration,\
  57. org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration,\
  58. org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration,\
  59. org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\
  60. org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration,\
  61. org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration,\
  62. org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration,\
  63. org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration,\
  64. org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration,\
  65. org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,\
  66. org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration,\
  67. org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,\
  68. org.springframework.boot.autoconfigure.jsonb.JsonbAutoConfiguration,\
  69. org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration,\
  70. org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration,\
  71. org.springframework.boot.autoconfigure.ldap.LdapAutoConfiguration,\
  72. org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration,\
  73. org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration,\
  74. org.springframework.boot.autoconfigure.mail.MailSenderValidatorAutoConfiguration,\
  75. org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration,\
  76. org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\
  77. org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration,\
  78. org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,\
  79. org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
  80. org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration,\
  81. org.springframework.boot.autoconfigure.reactor.core.ReactorCoreAutoConfiguration,\
  82. org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration,\
  83. org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration,\
  84. org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration,\
  85. org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration,\
  86. org.springframework.boot.autoconfigure.security.reactive.ReactiveUserDetailsServiceAutoConfiguration,\
  87. org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration,\
  88. org.springframework.boot.autoconfigure.session.SessionAutoConfiguration,\
  89. org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2ClientAutoConfiguration,\
  90. org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration,\
  91. org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\
  92. org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration,\
  93. org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration,\
  94. org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration,\
  95. org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration,\
  96. org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration,\
  97. org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration,\
  98. org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerFactoryAutoConfiguration,\
  99. org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration,\
  100. org.springframework.boot.autoconfigure.web.reactive.error.ErrorWebFluxAutoConfiguration,\
  101. org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration,\
  102. org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration,\
  103. org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration,\
  104. org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration,\
  105. org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration,\
  106. org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration,\
  107. org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,\
  108. org.springframework.boot.autoconfigure.websocket.reactive.WebSocketReactiveAutoConfiguration,\
  109. org.springframework.boot.autoconfigure.websocket.servlet.WebSocketServletAutoConfiguration,\
  110. org.springframework.boot.autoconfigure.websocket.servlet.WebSocketMessagingAutoConfiguration,\
  111. org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration

实现自动装配

首先梳理自动装配的流程

定义HelloWorldAutoConfiguration

  1. /** * @ClassName: HelloWorldAutoConfiguration * @Description: HelloWorld 自动装配 * @Author: 尚先生 * @CreateDate: 2019/1/28 * @Version: 1.0 */
  2. @Configuration // Spring 模式注解装配
  3. @EnableHelloWorld // Spring @Enable 模块装配
  4. public class HelloWorldAutoConfiguration {
  5. @Bean
  6. public String helloWorld() { // 方法名即 Bean 名称
  7. return "Hello,World sxs";
  8. }
  9. }

配置注解标记类

  1. /** * @ClassName: EnableHelloWorld * @Description: HelloWorld 自动装配注解 * @Author: 尚先生 * @CreateDate: 2019/1/28 * @Version: 1.0 */
  2. @Retention(RetentionPolicy.RUNTIME)
  3. @Target(ElementType.TYPE)
  4. @Documented
  5. @Import(HelloWorldConfiguration.class)
  6. public @interface EnableHelloWorld {
  7. }

配置META-INF/spring.factories

  1. org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  2. com.sxs.springboot.configuration.HelloWorldAutoConfiguration

测试实现结果

  1. /** * @ClassName: EnableHelloWorldBootstrap * @Description: HelloWorld 自动装配引导类(测试类) * @Author: 尚先生 * @CreateDate: 2019/1/28 * @Version: 1.0 */
  2. @EnableHelloWorld
  3. public class EnableHelloWorldBootstrap {
  4. public static void main(String[] args) {
  5. ConfigurableApplicationContext context = new SpringApplicationBuilder(EnableHelloWorldBootstrap.class)
  6. .web(WebApplicationType.NONE)
  7. .run(args);
  8. // helloWorld Bean 是否存在
  9. String helloWorld = context.getBean("helloWorld", String.class);
  10. System.out.println("helloWorld Bean : " + helloWorld);
  11. // 关闭上下文
  12. context.close();
  13. }
  14. }

测试结果

  1. helloWorld Bean : Hello,World sxs

自动装配的过程

  1. 1. 通过各种注解实现了类与类之间的依赖关系,容器在启动的时候Application.run,会调用EnableAutoConfigurationImportSelector.classselectImports方法(其实是其父类的方法)
  2. 2. selectImports方法最终会调用SpringFactoriesLoader.loadFactoryNames方法来获取一个全面的常用BeanConfiguration列表
  3. 3. loadFactoryNames方法会读取FACTORIES_RESOURCE_LOCATION(也就是spring-boot-autoconfigure.jar 下面的spring.factories),获取到所有的Spring相关的Bean的全限定名ClassName,大概120多个
  4. 4. selectImports方法继续调用filter(configurations, autoConfigurationMetadata);这个时候会根据这些BeanConfiguration里面的条件,来一一筛选,最关键的是
  5. @ConditionalOnClass,这个条件注解会去classpath下查找,jar包里面是否有这个条件依赖类,所以必须有了相应的jar包,才有这些依赖类,才会生成IOC环境需要的一些默认配置Bean
  6. 5. 最后把符合条件的BeanConfiguration注入默认的EnableConfigurationPropertie类里面的属性值,并且注入到IOC环境当中

往期文章

  1. 博客地址:https://blog.csdn.net/shang_xs
  2. 微信公众号地址:http://mp.weixin.qq.com/mp/homepage?__biz=MzUxMzk4MDc1OQ==&hid=2&sn=c6c58c06f6f8403af27b6743648b3055&scene=18#wechat_redirect

发表评论

表情:
评论列表 (有 0 条评论,425人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Spring Boot 自动装配原理

    > 本文已经收录到Github仓库,该仓库包含计算机基础、Java核心知识点、多线程、JVM、常见框架、分布式、微服务、设计模式、架构等核心知识点,欢迎star~ > > G