SpringBoot 自动装配原理

@SpringBootApplication 启动注解

@SpringBootApplication

public class SpringBootBasicLearnApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringBootBasicLearnApplication.class, args);
    }
}


	/**
	 * to store the base package from the importing configuration
	 * 也就是获取到我们启动类的包路径
	 */
	static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {

		@Override
		public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
      // 这里注入容器,将我们的包路径信息封装成一个Bean
			register(registry, new PackageImports(metadata).getPackageNames().toArray(new String[0]));
		}

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

	}



// BeanClassLoaderAware,ResourceLoaderAware 这些表示可以获取Aware前的信息
// Ordered 表示Bean注入排序
// 关键是这个: DeferredImportSelector  延迟导入选择器  extends 
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
		ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered
      
      
      
public interface DeferredImportSelector extends ImportSelector {
    // 这里是接口的定义方法,具体实现看AutoConfigurationImportSelector
		void process(AnnotationMetadata metadata, DeferredImportSelector selector);
}


@Override
		public void process(AnnotationMetadata annotationMetadata, DeferredImportSelector deferredImportSelector) {
			AutoConfigurationEntry autoConfigurationEntry = ((AutoConfigurationImportSelector) deferredImportSelector)
           // 这里是核心,获取自动配置的实例,通过元数据 !!! 
					.getAutoConfigurationEntry(annotationMetadata);
			this.autoConfigurationEntries.add(autoConfigurationEntry);
			for (String importClassName : autoConfigurationEntry.getConfigurations()) {
				this.entries.putIfAbsent(importClassName, annotationMetadata);
			}
		}


protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
		if (!isEnabled(annotationMetadata)) {
			return EMPTY_ENTRY;
		}
  	// 获取EnableAutoConfiguration注解中定义的exclude排除的Bean类
		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);
	}




protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
		List<String> configurations = new ArrayList<>(
				SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader()));
  	// 这里是关键,会找原先定义的所有Bean配置!!!
		ImportCandidates.load(AutoConfiguration.class, getBeanClassLoader()).forEach(configurations::add);
		return configurations;
	}


// 获取注解类的全类名集合
public static ImportCandidates load(Class<?> annotation, ClassLoader classLoader) {
  // LOCATION: "META-INF/spring/%s.imports"; 通过这个文件来找到所有自动配置类的信息
  // annotation.getName() = org.springframework.boot.autoconfigure.AutoConfiguration
  // 最终加载:META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
  // 这里直接下载源码,找Maven:org.springframework.boot:spring-boot-autoconfigure:2.7.5,一共有144个
  // 里面的就是默认启动的一个项,比如:org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,可以追一下源码
		String location = String.format(LOCATION, annotation.getName());
  	// 这里就读取到了所有的全类名集合
		Enumeration<URL> urls = findUrlsInClasspath(classLoaderToUse, location);
		List<String> autoConfigurations = new ArrayList<>();
		while (urls.hasMoreElements()) {
			URL url = urls.nextElement();
			autoConfigurations.addAll(readAutoConfigurations(url));
		}
    // 封装被返回
		return new ImportCandidates(autoConfigurations);
	}




// 这里就是过滤一部分不符合的类名
List<String> filter(List<String> configurations) {
			long startTime = System.nanoTime();
			String[] candidates = StringUtils.toStringArray(configurations);
			boolean skipped = false;
      // 通过过滤器 原来加载配置文件有144个,如果是基础SpringBoot项目,就剩13个了
			for (AutoConfigurationImportFilter filter : this.filters) {
				boolean[] match = filter.match(candidates, this.autoConfigurationMetadata);
				for (int i = 0; i < match.length; i++) {
					if (!match[i]) {
						candidates[i] = null;
						skipped = true;
					}
				}
			}
			if (!skipped) {
				return configurations;
			}
  
  
// 这里我们以META-INF中Redis自动装配类来演示
1. 查找 org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration
2. 查看源码
@AutoConfiguration
// 这里就是判断你容器内有没有这个类数据
@ConditionalOnClass(RedisOperations.class)
// 加载配置类,也就是我们在resource文件下写的内容,加载进来
@EnableConfigurationProperties(RedisProperties.class)
// 导如 Lettuce  Jedis 这都是我们熟悉的工具
@Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class })
public class RedisAutoConfiguration {

	@Bean
  // redisTemplate 工具
	@ConditionalOnMissingBean(name = "redisTemplate")
	@ConditionalOnSingleCandidate(RedisConnectionFactory.class)
	public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
		RedisTemplate<Object, Object> template = new RedisTemplate<>();
		template.setConnectionFactory(redisConnectionFactory);
		return template;
	}

	@Bean
  // StringRedisTemplate 工具
	@ConditionalOnMissingBean
	@ConditionalOnSingleCandidate(RedisConnectionFactory.class)
	public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
		return new StringRedisTemplate(redisConnectionFactory);
	}

}
// 核心点就是我们需要导入使用组件的核心位,比如我们使用Redis就要导入依赖
org.springframework.data.redis.core
 
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>