SpringBoot自动装配

前言:我们知道如果想将我们自己写的类注入IOC容器中只需要打上基础的@Component注解或者是@Configuration注解,但是SpringBoot是怎么加载我们在maven中导入的第三方SDK呢?

一般导入第三方库需要两个步骤:

  1. 下载第三方SDK(直接下载,maven,npm,pip)
  2. 导入(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中。

posted @ 2020-03-13 17:55  ChauncyL  阅读(283)  评论(0)    收藏  举报