源码解析-springboot自动装配

背景

springboot在启动过程中会自动加载配置文件中的类供后续使用,这个过程称为自动装配

引入@Import注解

springboot的启动类加入注解@SpringBootApplication,@SpringBootApplication注解中包含@EnableAutoConfiguration注解,@EnableAutoConfiguration这个注解中包含@Import(AutoConfigurationImportSelector.class)注解,springboot就是通过解析这个@Import注解来实现自动装配的

原理分析

  • springboot启动时会调用spring的核心方法refresh(),在refresh方法中调用invokeBeanFactoryPostProcessors(),这个方法用来执行beanFactory的一些后置处理器,处理一些比如注解解析的工作。这些后置处理器中有一个ConfigurationClassPostProcessor处理器,就是专门来解析注解的
  • @Import注解解析
@Nullable
	protected final SourceClass doProcessConfigurationClass(
			ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)
			throws IOException {

		if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
			//处理@Component注解及其内部类
		}

		// Process any @PropertySource annotations
		for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
				sourceClass.getMetadata(), PropertySources.class,
				org.springframework.context.annotation.PropertySource.class)) {
            //处理@PropertySource注解
		}

		// Process any @ComponentScan annotations
		Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
				sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
		if (!componentScans.isEmpty() &&
				!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
			//处理@ComponentScan注解
		}

		// Process any @Import annotations
        //注解@Import注解
		processImports(configClass, sourceClass, getImports(sourceClass), filter, true);

		// Process any @ImportResource annotations
		AnnotationAttributes importResource =
				AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
		if (importResource != null) {
			//处理@ImportResoure注解
		}

		// Process individual @Bean methods
        //处理@Bean注解
		Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
		for (MethodMetadata methodMetadata : beanMethods) {
			configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
		}

		// Process default methods on interfaces
        //处理接口的缺省方法
		processInterfaces(configClass, sourceClass);

		// Process superclass, if any
		if (sourceClass.getMetadata().hasSuperClass()) {
			//处理父类信息
		}

		// No superclass -> processing is complete
		return null;
	}

通过getImports(sourceClass)方法递归处理,获取所有@Import注解

private void collectImports(SourceClass sourceClass, Set<SourceClass> imports, Set<SourceClass> visited)
			throws IOException {

		if (visited.add(sourceClass)) {
			for (SourceClass annotation : sourceClass.getAnnotations()) {
				String annName = annotation.getMetadata().getClassName();
				if (!annName.equals(Import.class.getName())) {
                    //此处为递归处理,获取所有的@Import注解,放到imports集合中
					collectImports(annotation, imports, visited);
				}
			}
			imports.addAll(sourceClass.getAnnotationAttributes(Import.class.getName(), "value"));
		}
	}

执行processImports方法(注:只列出核心代码)

private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
			Collection<SourceClass> importCandidates, Predicate<String> exclusionFilter,
			boolean checkForCircularImports) {

		if (checkForCircularImports && isChainedImportOnStack(configClass)) {
			this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
		}
		else {
			this.importStack.push(configClass);
			try {
                //遍历所有import进来的类
				for (SourceClass candidate : importCandidates) {
					if (candidate.isAssignable(ImportSelector.class)) {
						// Candidate class is an ImportSelector -> delegate to it to determine imports
						Class<?> candidateClass = candidate.loadClass();
						ImportSelector selector = ParserStrategyUtils.instantiateClass(candidateClass, ImportSelector.class,
								this.environment, this.resourceLoader, this.registry);
						Predicate<String> selectorFilter = selector.getExclusionFilter();
						if (selectorFilter != null) {
							exclusionFilter = exclusionFilter.or(selectorFilter);
						}
						if (selector instanceof DeferredImportSelector) {
                            //自动装配所需的selector实现了DeferredImportSelector接口,所以要加入到延迟处理的集合,后续处理
							this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
						}
						else { //否则就会立即执行
							String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
							Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames, exclusionFilter);
                            //递归处理,import的类的类的类。。。
							processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);
						}
					}
					else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
						//。。。
					}
					else {
						//。。。
					}
				}
			}
			catch (BeanDefinitionStoreException ex) {
				throw ex;
			}
			catch (Throwable ex) {
				throw new BeanDefinitionStoreException(
						"Failed to process import candidates for configuration class [" +
						configClass.getMetadata().getClassName() + "]", ex);
			}
			finally {
				this.importStack.pop();
			}
		}
	}

处理延迟列表中的类,此时为AutoConfigurationImportSelector,调用getCandidateConfigurations()方法,获取spring.factories配置文件中的内容,根据getSpringFactoriesLoaderFactoryClass()方法返回的类文件作为key来筛选配置文件内容

protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
		if (!isEnabled(annotationMetadata)) {
			return EMPTY_ENTRY;
		}
		AnnotationAttributes attributes = getAttributes(annotationMetadata);
        //调用getCandidateConfigurations()方法获取配置文件spring.factories中的类路径
		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);
	}
  • spring.factories文件容截取
# Auto Configuration Import Filters
org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\
org.springframework.boot.autoconfigure.condition.OnBeanCondition,\
org.springframework.boot.autoconfigure.condition.OnClassCondition,\
org.springframework.boot.autoconfigure.condition.OnWebApplicationCondition

# 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
  • 取出对应value值之后,在根据一定的规则过滤,最后留下一批springboot需要的大概是25个,在遍历解析这些类上的注解,解析完之后,将对应的属性值赋值给beanDefinition,用户之后的初始化操作
  • 总结:
  1. 解析@Import注解,递归拿到AutoConfigurationImportSelector类,放入延迟处理列表deferredImportSelectors中
  2. 处理AutoConfigurationImportSelector。调用getCandidateConfigurations()方法,获取org.springframeword.boot.spring-boot-autoconfigure的jar包下META-INF/spring.factories配置文件中的内容
  3. 调用getSpringFactoriesLoaderFactoryClass()方法,返回的类文件的权限顶名做为key,去配置文件中value,拿到value列表之后,根据规则过滤,封装成AutoConfigurationEntry对象
  4. 继续处理这些从配置文件拿到的类,和上面的步骤一样,解析类上的注解
  5. 解析之后,合并到beanDefinition中,供后续的操作使用
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值