Spring 源码解析(三)注解配置全链路分析

1,243 阅读4分钟

前面我们了解了 Spring 容器的刷新逻辑xml的配置全链路解析 今天我们重点来看一下 注解方式的 bean 如何注册到 Spring 容器之中。

Configuration 注解启动分析

实例

创建一个注解方式的实体类

@Component
public class Device {
	private String name = "device";
}

使用注解配置方式启动:

ApplicationContext context1 = new AnnotationConfigApplicationContext(Device.class);
Device bean = context1.getBean(Device.class);
System.out.println(bean);

我们看一下输出结果:

13:56:52.981 [main] DEBUG org.springframework.context.annotation.AnnotationConfigApplicationContext - Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@dcf3e99
13:56:53.004 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalConfigurationAnnotationProcessor'
13:56:53.060 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerProcessor'
13:56:53.063 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerFactory'
13:56:53.065 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalAutowiredAnnotationProcessor'
13:56:53.066 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalCommonAnnotationProcessor'
13:56:53.077 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'device'
com.mrlsm.spring.demo.entity.Device@2bea5ab4

运行成功,说明 Device 类使用注解被 Spring 容器所管理了。 ​

接下来我们之间分析一下 AnnotationConfigApplicationContext 支持 Configuration 注解启动 spring 容器的原理。

一、AnnotationConfigApplicationContext

public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
	//调用默认无参构造器,主要初始化 AnnotatedBeanDefinitionReader
	// 以及路径扫描器 ClassPathBeanDefinitionScanner
	this();
	//把传入的 Class 进行注册, Class 既可以有 @Configuration注解,也可以没有 @Configuration注解
	//如何注册委托给了 org.springframework.context.annotation.AnnotatedBeanDefinitionReader.register 方法进行注册
	// 包装传入的 Class 生成 BeanDefinition , 注册到 BeanDefinitionRegistry
	register(componentClasses);
	refresh();
}

我们查看下本身的构造方法:

public AnnotationConfigApplicationContext() {
	this.reader = new AnnotatedBeanDefinitionReader(this);
	this.scanner = new ClassPathBeanDefinitionScanner(this);
}

初始化了一个 BeanDefinitionReader 与 BeanDefinitionScanner 容器来为稍后通过调用其 register() 方法注册配置类,并调用 refresh() 方法刷新容器,触发容器对注解 Bean 的载入、解析和注册过程。 ​

二、AnnotatedBeanDefinitionReader#doRegisterBean

看源码可以发现 AnnotatedBeanDefinitionReader#register 最终使用的为 doRegisterBean() 方法

private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
								@Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier,
								@Nullable BeanDefinitionCustomizer[] customizers) {

	AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
	//用于处理 Conditional 注解,在特定条件下阻断 bean 的注册
	if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
		return;
	}
	//用来创建 bean 的 supplier,会替代掉 bean 本身的创建方法
	//instanceSupplier 一般情况下为 null
	abd.setInstanceSupplier(supplier);
	//此行代码处理 scope 注解,本例中 scope 是默认值 singleton
	ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
	abd.setScope(scopeMetadata.getScopeName());
	//获取beanName
	String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
	//特定注解解析,本例中均没传入dependsOn,LazyInit这些注解
	//这些注解就和<bean>标签里面的属性作用是一样的
	AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
	//本例中 qualifiers 传入的是 null,qualifiers就是用来决定接口的实现类的
	if (qualifiers != null) {
		for (Class<? extends Annotation> qualifier : qualifiers) {
			if (Primary.class == qualifier) {
				abd.setPrimary(true);
			}
			else if (Lazy.class == qualifier) {
				abd.setLazyInit(true);
			}
			else {
				abd.addQualifier(new AutowireCandidateQualifier(qualifier));
			}
		}
	}
	//主要提供对BeanDefinition的一些定制化操作
	if (customizers != null) {
		for (BeanDefinitionCustomizer customizer : customizers) {
			customizer.customize(abd);
		}
	}
	
        // 用 BeanDefinitionHolder 包装 BeanDefinition
	BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
        // 此行代码与动态代理和 scope 注解有关,主要看看是否依照 Spring 的 scope 生成动态代理对象
	// 但是在本案例中没有做任何操作,只是返回了传入的 definitionHolder
	definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
	// 向容器注册扫描到的 Bean
	BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}

该方法主要就是使用 AnnotatedGenericBeanDefinition 对象将对应的 class 对象包装起来,之后主要是处理定义在类上的其他注解,解析属性并给实例赋值。 之后使用 BeanDefinitionHolder 包装 BeanDefinition,之后调用 AnnotationConfigUtils#applyScopedProxyMode 跟进可以发现最终调用的为 ScopedProxyUtils#createScopedProxy ​

三、ScopedProxyUtils#createScopedProxy

该方法主要是为提供的目标 bean 生成范围代理,使用内部名称注册目标 bean 并在范围代理上设置 "targetBeanName"。

public static BeanDefinitionHolder createScopedProxy(BeanDefinitionHolder definition,
													 BeanDefinitionRegistry registry, boolean proxyTargetClass) {

	String originalBeanName = definition.getBeanName();
	BeanDefinition targetDefinition = definition.getBeanDefinition();
	String targetBeanName = getTargetBeanName(originalBeanName);

	// 为原始 bean 名称创建范围代理定义,
	// 在内部目标定义中“隐藏”目标 bean.
	RootBeanDefinition proxyDefinition = new RootBeanDefinition(ScopedProxyFactoryBean.class);
	proxyDefinition.setDecoratedDefinition(new BeanDefinitionHolder(targetDefinition, targetBeanName));
	proxyDefinition.setOriginatingBeanDefinition(targetDefinition);
	proxyDefinition.setSource(definition.getSource());
	proxyDefinition.setRole(targetDefinition.getRole());

	proxyDefinition.getPropertyValues().add("targetBeanName", targetBeanName);
	if (proxyTargetClass) {
		targetDefinition.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
		// ScopedProxyFactoryBean 的“proxyTargetClass”默认为 TRUE,所以我们不需要在这里明确设置它。
	} else {
		proxyDefinition.getPropertyValues().add("proxyTargetClass", Boolean.FALSE);
	}

	// 从原始 bean 定义复制自动装配设置。
	proxyDefinition.setAutowireCandidate(targetDefinition.isAutowireCandidate());
	proxyDefinition.setPrimary(targetDefinition.isPrimary());
	if (targetDefinition instanceof AbstractBeanDefinition) {
		proxyDefinition.copyQualifiersFrom((AbstractBeanDefinition) targetDefinition);
	}

	// 应该忽略目标 bean 以支持范围代理。
	targetDefinition.setAutowireCandidate(false);
	targetDefinition.setPrimary(false);

	// 在工厂中将目标 bean 注册为单独的 bean。
	registry.registerBeanDefinition(targetBeanName, targetDefinition);

	// 将作用域代理定义作为主 bean 定义返回
	// (potentially an inner bean).
	return new BeanDefinitionHolder(proxyDefinition, originalBeanName, definition.getAliases());
}

完成上述操作后,AnnotatedBeanDefinitionReader#doRegisterBean 方法最后就是向容器注册扫描到的 Bean 也就是调用 BeanDefinitionReaderUtils#registerBeanDefinition 方法。 看到这,是不是感觉熟悉,没错和 xml 配置的解析 一样调用到 BeanDefinitionReaderUtils#registerBeanDefinition 方法将 beanDefinition 注册到 DefaultListableBeanFactory 实例里面。

普通注解启动分析

那么对于普通注解的 bean 呢? 我们对 main 方法做下修改:将 Device 不作为直接参数传入 AnnotationConfigApplicationContext

ApplicationContext context = new AnnotationConfigApplicationContext(DemoApplication.class);
Device bean = context.getBean(Device.class);
System.out.println(bean);

此时我们运行成功后,我们对 DefaultListableBeanFactory#registerBeanDefinition 中打上断点观察:

image.png

看他的调用栈,发现执行到 refresh 方法后才将 BeanDefinition 注册到 DefaultListableBeanFactory 实例里面。 好,看调用栈跟进 PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors 方法 我们跟进该方法:

public static void invokeBeanFactoryPostProcessors(
		ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

	// 如果有 BeanDefinitionRegistryPostProcessor 的话优先执行
	Set<String> processedBeans = new HashSet<>();
	// 如果是 BeanDefinitionRegistry 类型的话
	if (beanFactory instanceof BeanDefinitionRegistry) {
		BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
		// 用于记录常规 BeanFactoryPostProcessor
		List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
		// 用于记录 BeanDefinitionRegistryPostProcessor
		List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
		// 遍历所有参数传递进来的 BeanFactoryPostProcessor (它们并没有作为 bean 注册在容器中)
		// 将所有参数传入的 BeanFactoryPostProcessor 分成两组 :
		// BeanDefinitionRegistryPostProcessor 和 常规的 BeanFactoryPostProcessor
		// 1.如果是 BeanDefinitionRegistryPostProcessor,现在执行 postProcessBeanDefinitionRegistry(),
		// 2.否则记录为一个常规的 BeanFactoryPostProcessor,暂时不执行处理
		for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
			if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
				BeanDefinitionRegistryPostProcessor registryProcessor =
						(BeanDefinitionRegistryPostProcessor) postProcessor;
				registryProcessor.postProcessBeanDefinitionRegistry(registry);
				registryProcessors.add(registryProcessor);
			}
			else {
				regularPostProcessors.add(postProcessor);
			}
		}

		// 用于记录当前正要被执行的 BeanDefinitionRegistryPostProcessor
		List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

		// 首先,对实现了优先级顺序接口的 Bean 形式的 BeanDefinitionRegistryPostProcessor 进行调用
		// 找出所有容器中注册为 BeanDefinitionRegistryPostProcessor 的 postProcessor 名字数组
		// 注意,这里不会直接实例化这个 bean(主要是这些 PostProcessor 需要按顺序初始化和调用,先调用的 PostProcessor 是可能对后初始化的 bean 造成影响的)
		String[] postProcessorNames =
				beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
		for (String ppName : postProcessorNames) {
			// 遍历容器,将 BeanDefinitionRegistryPostProcessor 类型的后置处理器 Bean 实例给添加到当前的注册处理器中
			if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
				currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
				processedBeans.add(ppName);
			}
		}
		// 根据优先级排序 对所有实现了 PriorityOrdered 接口的 PostProcessor 排序
		sortPostProcessors(currentRegistryProcessors, beanFactory);
		// 加入 registryProcessors 列表
		registryProcessors.addAll(currentRegistryProcessors);
		// 调用 BeanDefinitionRegistryPostProcessor 的方法,ConfigurationClassPostProcessor 的逻辑就是在这里被调用的
		invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
		// 清除 currentRegistryProcessors
		currentRegistryProcessors.clear();

		// 其次对实现了 Ordered 接口的 BeanDefinitionRegistryPostProcessors 进行调用
		postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
		for (String ppName : postProcessorNames) {
			if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
				currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
				processedBeans.add(ppName);
			}
		}
		// 按照 Order 排序 与 上方方法类似
		sortPostProcessors(currentRegistryProcessors, beanFactory);
		registryProcessors.addAll(currentRegistryProcessors);
		invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
		currentRegistryProcessors.clear();

		// 接下来处理普通的,没实现排序接口的 BeanDefinitionRegistryPostProcessor
                // 需要主要的是,这里有一个循环,主要原因是 BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry 方法是传入了一个 BeanDefinitionRegistry 的实例
                // 这意味着我们可以在(实际上正常实现这个接口就是为了注册 beanDefinition 的)这个 PostProcessor 注册新的 beanDefinition
                // 而新注册的 beanDefinition 对应的类也是可能实现 BeanDefinitionRegistryPostProcessor 接口的,所以这里需要循环处理,直到不会注册新的 BeanDefinitionRegistryPostProcessor 为止
		boolean reiterate = true;
		while (reiterate) {
			reiterate = false;
			postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
			for (String ppName : postProcessorNames) {
				if (!processedBeans.contains(ppName)) {
					currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
					processedBeans.add(ppName);
					reiterate = true;
				}
			}
			sortPostProcessors(currentRegistryProcessors, beanFactory);
			registryProcessors.addAll(currentRegistryProcessors);
			invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
			currentRegistryProcessors.clear();
		}

		// 因为 BeanDefinitionRegistryPostProcessor 继承自 BeanFactoryPostProcessor,所以这里
		// 也对所有 BeanDefinitionRegistryPostProcessor 调用其方法 postProcessBeanFactory()
		invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
		// 对所有常规 BeanFactoryPostProcessor 调用其方法 postProcessBeanFactory()
		invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
	}

	else {
		//如果都是常规的 BeanFactoryPostProcessor,则调用其方法 postProcessBeanFactory()
		invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
	}
	
	// 上面逻辑执行了以参数形式传入的 BeanDefinitionRegistryPostProcessor 以及常规的 BeanFactoryPostProcessor
	// 也执行了容器里面的 BeanDefinitionRegistryPostProcessor,故还剩下容器里面的 BeanFactoryPostProcessor 需要去处理
	// 逻辑是一样的,也分为实现了 PriorityOrdered和Ordered 以及两个都没实现的 postProcessor
	// ···
}

该方法很长,但是主要逻辑类似,主要是分情况处理不同类型的 BeanFactoryPostProcessors。

  1. BeanFacotryPostProcessors 主要分为两类,一类是 BeanDefinitionRegistry 的 BeanFactoryPostProcessor,另外一类是常规的 BeanFactoryPostProcessor。优先处理前者。
  2. 同时,这两种后置处理器又被分为从参数里传入和从容器里获取的,最终要将从参数里获取的和从容器里获取的合并在一起。合并的时候又分为实现了PriorityOrder和普通Order以及没有实现这两个接口的,实现了 PriorityOrdered 的先执行。
  3. 同时是按照PriorityOrdered顺序执行的,其次再到 Order,按照 Order 执行,最后才是没实现这两个接口的。
  4. 先执行完 BeanDefinitionRegistryPostProcessor 的 invokeBeanDefinitionRegistryPostProcessors 方法,再对 BeanDefinitionRegistryPostProcessor 执行 invokeBeanFactoryPostProcessors 方法, 之后再对常规的 BeanFacotryPostProcessors 执行 invokeBeanFactoryPostProcessors 方法。

我们可以看下里面的 invokeBeanDefinitionRegistryPostProcessors 和 invokeBeanFactoryPostProcessors 方法,具体是怎么实现的。

private static void invokeBeanDefinitionRegistryPostProcessors(
    Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {

    for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
        postProcessor.postProcessBeanDefinitionRegistry(registry);
    }
}

private static void invokeBeanFactoryPostProcessors(
    Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {

    for (BeanFactoryPostProcessor postProcessor : postProcessors) {
        postProcessor.postProcessBeanFactory(beanFactory);
    }
}

可以明确的看出,就是一个简单的循环调用。 ​

总结

这篇我们主要分析了注解配置全链路分析,与上一篇 xml的配置全链路解析 有相同的部分,Spring 容器都是在 refresh 方法中完成对 bean 的注册。 ​

本文基于 spring-framework 5.2.10.RELEASE 版本进行分析