SpringBoot的自动装配原理


介绍:springboot的自动装配原理,从启动类上的注解来解释

@SpringBootApplication

@SpringBootApplication详解

@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
		@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {

可以看见这是一个合成注解,我们挨个分析每个注解的作用

@SpringBootConfiguration

@Documented
@Configuration
public @interface SpringBootConfiguration {

@Configuration代表了这是一个配置类,也就是我们的mian程序也是一个配置类

@ComponentScan

这个注解是用来包扫描的

@EnableAutoConfiguration

@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {

可以看见这是两个注解的合成注解

@AutoConfigurationPackage

@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage {

自动配置包,可以看见它使用了@Import 这个注解,这是给容器导入一个组件。我们点进入这个Registrar

	static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {

		@Override
		public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
			register(registry, new PackageImports(metadata).getPackageNames().toArray(new String[0]));
		}

		@Override
		public Set<Object> determineImports(AnnotationMetadata metadata) {
			return Collections.singleton(new PackageImports(metadata));
		}

	}

Registrar类的作用是给容器中导入一系列组件。

public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry)

AnnotationMetadata 代表注解的元信息,也就是得到@AutoConfigurationPackage 注解的元信息。但这个注解实际的作用类是我们的启动类上面,如下图
在这里插入图片描述
然后在此方法中,得到我们的主启动类所在的包名,并注册到一个数组中

PackageImports(metadata).getPackageNames().toArray(new String[0])

在这里插入图片描述
所以@AutoConfigurationPackage是把主启动类所在的包下的所有组件批量注册。这也是我们的默认的包扫描的规则

@Import(AutoConfigurationImportSelector.class)

我们进入AutoConfigurationImportSelector类的下面这个方法

	public String[] selectImports(AnnotationMetadata annotationMetadata) {
		if (!isEnabled(annotationMetadata)) {
			return NO_IMPORTS;
		}
		//我们进入这个方法,这个方法就是批量导入组件的方法
		AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);
		return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
	}

	protected AutoConfigurationEntry getAutoConfigurationEntry(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 = getConfigurationClassFilter().filter(configurations);
		fireAutoConfigurationImportEvents(configurations, exclusions);
		return new AutoConfigurationEntry(configurations, exclusions);
	}

在这里插入图片描述

在下面这个方法中,利用工厂加载,得到所有的MEAT-INF/spring.factories的位置的其中的文件

	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;
	}

比如说在spring-boot-autoconfigure这个jar包下面就有127个要导入的配置项,官方提供的127个场景就全包括在此。

但加载不是意味着生效,springboot可以做到按需开启。SpringBoot有一个注解@Conditional,只有满足了@Conditional注解以及其子注解的要求,配置类才会生效

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值