SpringBoot自动加载

SpringBoot自动装配

Spring的自动装配机制简单来说就是将各种需要的Bean装配进框架容器中。

SpringBoot自动装配分为两类:

  1. 自动装配本项目Bean
  2. 自动装配依赖jar包下提供的bean

一起来看下SpringBoot是怎样加载的。很显然,SpringBoot项目是从main方法开始启动的,这个方法中做了什么呢?

image-20220423144835414

在这里可以看到Spring将自身类加载进了容器中,这里跟spring加载配置类进容器一样。至于为什么加载这个类进容器就会自动装配好所有需要的bean信息,就是下面要说的。重点对象就是@SpringBootApplication。

我们来进入@SpringBootApplication看一下里面做了什么。

image-20220423145211870

这里面重点对象包含三个:

@SpringBootConfiguration

image-20220423145355502

@EnableAutoConfiguration

image-20220423145432134

@ComponentScan

先来说一下@SpringBootConfiguration,@SpringBootConfiguration中包含了@Configuration,也就是说run()方法加载进去的是一个配置类,配置类中是可以对其他bean进行配置的。这就让这个启动类有了加载bean的权限。

而@ComponentScan就是将包下的所有Bean加载进容器,在这里就是将这个类所在的包下所有bean加载进容器。

所以为什么启动类一定要在项目根包下就不难理解了。这里加载的是本项目的bean。

看@EnableAutoConfiguration之前,我们先来看一下@Import注解的玩法

@Import也将bean加载进容器的注解,不同的是这个注解有三种加载方式,可以变着姿势对bean进行加载。只要思想不滑坡。

[@Import加载bean的三种方法:]((60条消息) @Import注解的作用_一直打铁的博客-CSDN博客_@import)

  1. 导入普通类

    @Import({TestA.class})
    @Configuration
    public class ImportConfig {
    }
    
  2. 导入一个实现了DeferredImportSelector接口的类

    实现了ImportSelector接口的类会重写一个selectImports,这个方法会将返回的字符串数组中的bean加载进容器(重点)。这是唯一一种可以批量加载bean的。

    @Import({SelfImportSelector.class})
    @Configuration
    public class ImportConfig {
    }
    
    public class SelfImportSelector implements ImportSelector {
        @Override
        public String[] selectImports(AnnotationMetadata importingClassMetadata) {
            return new String[]{"com.test.importdemo.TestC"};
        }
    }
    
    
  3. 导入一个实现了ImportBeanDefinitionRegistrar接口的类

    这个类会重写registerBeanDefinitions方法,在这个方法中可以对类进行加载

    @Import({SelfImportBeanDefinitionRegistrar.class})
    @Configuration
    public class ImportConfig {
    }
    
    public class SelfImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
        @Override
        public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
            RootBeanDefinition root = new RootBeanDefinition(TestD.class);
            registry.registerBeanDefinition("testD", root);
        }
    }
    

了解完@Import的用法,让我们再回到@EnableAutoConfiguration注解中。

![image-20220423145432134](https://ling-28.oss-cn-beijing.aliyuncs.com/img/image-20220423145432134.png

@EnableAutoConfiguration中的注解@Import加载了一个AutoConfigurationImportSelector.class,让我们看一下这个类做了什么。从里面我看到了这个方法。很显然是用了@Import的第二种方法进行加载bean。具体加载了什么bean呢,再深入探探。

@Override
	public String[] selectImports(AnnotationMetadata annotationMetadata) {
		if (!isEnabled(annotationMetadata)) {
			return NO_IMPORTS;
		}
		AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);
		return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
	}

这是getAutoConfigurationEntry方法的具体实现:

protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
		if (!isEnabled(annotationMetadata)) {
			return EMPTY_ENTRY;
		}
    	//从jar包中加载class
    	// 这里获取class是从classpath下的jar包中的META-INF/spring.factories中读取到的
		AnnotationAttributes attributes = getAttributes(annotationMetadata);
		List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
   		//过滤掉重复的class文件 
		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);
	}

依赖的jar包中有会在META-INF下包含spring.factories文件

image-20220423171730309

在自动加载流程中会把EnableAutoConfiguration作为key,下面的class会以“,”隔开作为值,进行读取加载。注:这些class大多都会是jar包中提供给你的Configuration文件,Configuration中会给你提供对外的bean。你导入依赖后能调用的bean就是从这里来的。
菜鸟一个,错误的地方还望指出,拓展的知识希望大佬能跟我讲解一下。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值