SpringBoot自动装配
Posted chauncyl
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringBoot自动装配相关的知识,希望对你有一定的参考价值。
前言:我们知道如果想将我们自己写的类注入IOC容器中只需要打上基础的@Component注解或者是@Configuration注解,但是SpringBoot是怎么加载我们在maven中导入的第三方SDK呢?
一般导入第三方库需要两个步骤:
- 下载第三方SDK(直接下载,maven,npm,pip)
- 导入(import)
SpringBoot的自动配置原理与上述稍稍不同:
1.首先从SpringBoot入口文件@SpringBootApplication讲起,这个注解内部又包装了三个重要的注解,正是这三个注解实现了SpringBoot自动装配功能。
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
2.@SpringBootConfiguration:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration{
这个注解基础就是一个基础@Component注解,将bean注入到IOC容器中。
3.@EnableAutoConfiguration:内部通过反射导入了自动装配选择器
@Import(AutoConfigurationImportSelector.class)
AutoConfigurationImportSelector:
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
.loadMetadata(this.beanClassLoader);
AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(autoConfigurationMetadata,
annotationMetadata);
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
protected AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata,
AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
AnnotationAttributes attributes = getAttributes(annotationMetadata);
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
configurations = removeDuplicates(configurations);
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
configurations = filter(configurations, autoConfigurationMetadata);
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
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;
}
这个选择器最终返回一个string对象,即为需要装配的配置类名。如何获取的呢?这里只贴出部分关键代码:首先selectImports函数中调用getAutoConfigurationEntry,getAutoConfigurationEntry调用getCandidateConfigurations(关键),这个函数中调用SpringFactoriesLoader.loadFactoryNames加载了spring-boot-autoconfigure中的spring.factories文件。而spring.factories中的键值对就是要装配的配置类名,在maven中引入后springboot便将配置类名添加到spring.factories中了。
spring.factories:
#Auto Configure
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.CloudServiceConnectorsAutoConfiguration,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.CassandraReactiveDataAutoConfiguration,org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveRepositoriesAutoConfiguration,
4.@ComponentScan:该注解将自动将和SpringBoot入口文件同级的包扫描,寻找bean。定义Spring Beans的第一步是使用正确的注解@Component或@Service或@Repository。但是,Spring不知道你定义了某个bean除非它知道从哪里可以找到这个bean。作用:配合@Component一起食用将自己写的bean注册到IOC中。
为什么springboot这么麻烦?
因为springboot不仅仅时简单的导入类,而是将类加载到注册到IOC中。
以上是关于SpringBoot自动装配的主要内容,如果未能解决你的问题,请参考以下文章