一、什么是自动配置
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
类存在时才会生效。