关于spring:springboot自动配置的秘密

28次阅读

共计 4183 个字符,预计需要花费 11 分钟才能阅读完成。

​前言

       随着互联网越来越风行,springboot 曾经成为咱们无论是工作,还是面试当中,不得不把握的技术。说起 springboot 笔者认为最重要的性能非主动配置莫属了,为什么这么说?如果参加过以前 spring 简单我的项目的敌人必定,有过这样的经验,每次须要一个新性能,比方事务、AOP 等,须要大量的配置,须要导出找 jar 包,时不时会呈现 jar 兼容性问题,能够说苦不堪言。

      springboot 的呈现得益于“习惯优于配置”的理念,没有繁琐的配置、难以集成的内容(大多数风行第三方技术都被集成),这是基于 Spring 4.x 以上的版本提供的按条件配置 Bean 的能力。有了 springboot 的主动配置的性能,咱们能够疾速的开始一个我的项目。

一 什么是主动配置

不晓得敌人们在工作当中有没有这样的经验:

1.1 引入 redisTemplate

只有咱们在 pom.xml 文件中引入 spring-boot-starter-data-redis-xxx.jar 包,而后只有在配置文件中配置 redis 连贯,如:

spring.redis.database = 0
spring.redis.timeout = 10000
spring.redis.host = 10.72.16.9
spring.redis.port = 6379
spring.redis.pattern = 1

就能够在 service 办法中间接注入 StringRedisTemplate 对象的实例,能够间接应用了。敌人们有没有想过这是为什么?

@Autowired
private StringRedisTemplate stringRedisTemplate;

1.2  引入 transactionTemplate

在我的项目中只有引入 spring-boot-starter-xxx.jar,事务就主动失效了,并且能够间接在 service 办法中间接注入 TransactionTemplate,用它开发编程式事务代码。是不是很神奇?这又是为什么?

1.3  应用 @ConfigurationProperties

应用 @ConfigurationProperties 能够把指定门路下的属性,间接注入到实体对象中,看看上面这个例子:

@Data
@Component
@ConfigurationProperties("jump.threadpool")
public class ThreadPoolProperties {
​
 private int corePoolSize;
 private int maxPoolSize;
 private int keepAliveSeconds;
 private int queueCapacity;
}

只有 application.properties 这样配置,就能够主动注入到下面的实体中

jump.threadpool.corePoolSize=8
jump.threadpool.maxPoolSize=16
jump.threadpool.keepAliveSeconds=10
jump.threadpool.queueCapacity=100

没错,这三个例子都是 springboot 主动配置在起作用,咱们分为两种状况:bean 的主动配置 和 属性的主动配置。

二 工作原理


2.1 bean 的主动配置

Spring Boot 的启动类上有一个 @SpringBootApplication 注解,这个注解是 Spring Boot 我的项目必不可少的注解。

咱们先看看 @SpringBootApplication 注解

它下面定义了另外一个注解:@EnableAutoConfiguration

该注解的要害性能由 @Import 提供,其导入的 AutoConfigurationImportSelector 的 selectImports()办法通过 SpringFactoriesLoader.loadFactoryNames()扫描所有具备 META-INF/spring.factories 的 jar 包上面 key 是 EnableAutoConfiguration 全名的,所有主动配置类。

咱们看看 springboot 的 spring-boot-autoconfigure-xxx.jar

该 jar 包外面就有 META-INF/spring.factories 文件。

这个 spring.factories 文件是一组一组的 key=value 的模式,其中一个 key 是 EnableAutoConfiguration 类的全类名,而它的 value 是一个 xxxxAutoConfiguration 的类名的列表,这些类名以逗号分隔。

@EnableAutoConfiguration 注解通过 @SpringBootApplication 被间接的标记在了 Spring Boot 的启动类上。在 SpringApplication.run(…)的外部就会执行 selectImports()办法,找到所有 JavaConfig 主动配置类的全限定名对应的 class,而后将所有主动配置类加载到 Spring 容器中。

SpringApplication.run(…)办法怎么调到 selectImports()办法的

加载过程大略是这样的:

SpringApplication.run(…)办法》

AbstractApplicationContext.refresh()办法》

invokeBeanFactoryPostProcessors(…)办法》

PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(…) 办法》

ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(..)办法》

AutoConfigurationImportSelector.selectImports

该办法会找到主动配置的类,并给打了 @Bean 注解的办法创建对象。

postProcessBeanDefinitionRegistry 办法是最外围的办法,它负责解析 @Configuration、@Import、@ImportSource、@Component、@ComponentScan、@Bean 等,实现 bean 的主动配置性能。

回到刚刚第二个例子 TransactionTemplate 为什么能够间接援用?

是因为在 spring-boot-autoconfigure-xxx.jar 的 spring.factories 配置文件中,EnableAutoConfiguration 全类名下配置了 TransactionAutoConfiguration 全类名,springboot 在启动的时候会加载这个类。

而 TransactionAutoConfiguration 类是一个配置类,它外面创立 TransactionTemplate 类的实例。

这样在其余中央就能够间接注入 TransactionTemplate 类的实例。

2.2 属性的主动配置

属性的主动配置是通过 ConfigurationPropertiesBindingPostProcessor 类的 postProcessBeforeInitialization 办法实现,

public Object postProcessBeforeInitialization(Object bean, String beanName)
 throws BeansException {
 ConfigurationProperties annotation = getAnnotation(bean, beanName,
 ConfigurationProperties.class);
 if (annotation != null) {bind(bean, beanName, annotation);
 }
 return bean;
}

它会解析 @ConfigurationProperties 注解上的属性,将配置文件中对应 key 的值绑定到属性上。

三 主动配置的失效条件

每个 xxxxAutoConfiguration 类上都能够定义一些失效条件,这些条件根本都是从 @Conditional 派生进去的。

罕用的条件如下:

@ConditionalOnBean:当容器里有指定的 bean 时失效
@ConditionalOnMissingBean:当容器里不存在指定 bean 时失效
@ConditionalOnClass:当类门路下有指定类时失效
@ConditionalOnMissingClass:当类门路下不存在指定类时失效
@ConditionalOnProperty:指定的属性是否有指定的值,比方 @ConditionalOnProperties(prefix=”xxx.xxx”, value=”enable”, matchIfMissing=true),代表当 xxx.xxx 为 enable 时条件的布尔值为 true,如果没有设置的状况下也为 true。

举个比拟罕用的例子看看 TransactionAutoConfiguration,是如何应用条件的

咱们能够看到,条件用的是:@ConditionalOnClass,示意 TransactionAutoConfiguration 类只有在 PlatformTransactionManager 类存在时才会失效。

如何自定义主动配置类?

请浏览《老司机手把手教你编写本人的 springboot starter》外面有具体步骤。

总结

本篇文章从什么是主动配置,工作原理 和 主动配置的失效条件 三个方面介绍了主动配置的相干知识点。主动配置又分为:bean 的主动配置 和 属性的主动配置,二者的实现原理不一样。主动配置的失效条件用得十分多,倡议敌人们好好钻研一下。至于如何自定义主动配置类,本篇没有讲,是因为我在另外一篇文章《老司机手把手教你编写本人的 springboot starter》中认真介绍过的,有须要的敌人能够自行查阅。

如果这篇文档对您有所帮忙的话,麻烦关注一下我的公众账号:苏三说技术,或者帮忙点赞或转发,保持原创不易,您的反对是我保持最大的能源。前面我会分享更多更实用的干货,谢谢大家的反对。

正文完
 0