springboot的自动装配在springboot autoconfigure子项目中完成。
@SpringBootApplication
从springboot 入口注解开始
@SpringBootApplication
点进去能看到有一个@EnableAutoConfiguration注解。
@EnableAutoConfiguration
public @interface SpringBootApplication
继续点击EnableAutoConfiguration注解。
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
@Import注解引入了一个AutoConfigurationImportSelector类型的bean。继续点击AutoConfigurationImportSelector,进入之后找到方法getCandidateConfigurations().
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,
AnnotationAttributes attributes) {
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(
getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());
Assert.notEmpty(configurations,
"No auto configuration classes found in META-INF/spring.factories. If you "
+ "are using a custom packaging, make sure that file is correct.");
return configurations;
}
断言的意思:在META-INF/spring.factories下没发现配置类。配置类的配置是在META-INF/spring.factories文件下的。找到springboot autoconfigure 项目下的META-INF/spring.factories文件。
打开配置文件(贴部分自动装配的代码):这里需要自动装配的类配置。
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration
到这里应该已经理解到一些了,spring将需要自动装配的类写在META-INF/spring.factories文件里面,再启动的时候去读取需要配置的类,并进行自动装配。
跟踪代码:loadFactoryNames方法
SpringFactoriesLoader.loadFactoryNames(
getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());
public static List<String> loadFactoryNames(Class<?> factoryClass, @Nullable ClassLoader classLoader) {
String factoryClassName = factoryClass.getName();
return (List)loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList());
}
查看loadSpringFactories方法,贴个截图,正是去META-INF/spring.factories读取配置。
spring ioc加载之bean工厂后处理器的处理
回到getCandidateConfigurations方法,结合spring ioc的加载流程理解。
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,
AnnotationAttributes attributes) {
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(
getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());
return configurations;
}
找到debug模式下的调用流程图
refresh 》 处理bean工厂的后处理器 》 bean定义注册器后处理器 》 解析配置类 》 处理Import注解引入的AutoConfigurationImportSelector 》 读取META-INF/spring.factories下申明的配置类。
在bean定义扫描的时候,去META-INF/spring.factories这个文件里面读取需要自动装配的配置类,并将其添加到bean定义中。
在META-INF/spring.factories有申明redis自动装载,以redis为例讲一讲。
@Configuration
@ConditionalOnClass(RedisOperations.class)
@EnableConfigurationProperties(RedisProperties.class)
@Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class })
public class RedisAutoConfiguration
@Configuration注解,这个类是一个配置类
@EnableConfigurationProperties(RedisProperties.class) 引用RedisProperties这个属性类
再看RedisProperties这个类
@ConfigurationProperties(prefix = "spring.redis")
public class RedisProperties {
@ConfigurationProperties(prefix = "spring.redis")这一行,spring.redis很熟悉,就是spring boot配置文件中对redis的配置,如果有就覆盖,没有就使用默认的参数配置。
自动装配的大致原理
以redis举例
先置条件
1.一个约定好的配置类RedisProperties。
2.一个配置类RedisAutoConfiguration,在配置类中以@Bean注解方式返回redistemplate
@Bean
@ConditionalOnMissingBean(name = "redisTemplate")
public RedisTemplate<Object, Object> redisTemplate(
RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
触发条件
3.@SpringBootApplication注解》@EnableAutoConfiguration》@Import(AutoConfigurationImportSelector.class)
4.spring加载ioc在处理bean工厂后处理器的步骤,解析配置类。处理
@Import注解。AutoConfigurationImportSelector实现了DeferredImportSelector接口,并且重写了selectImports。在selectImports调用了getCandidateConfigurations。getCandidateConfigurations完成加载自动加载配置类。返回,这个时候还是bean定义。
- 在bean定义转换为bean的时候,完成自动装配。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。