spring5源码篇(2)——BeanDefinition的注册

spring-framework 版本:v5.3.19

注解方式(AnnotationConfigApplicationContext)

AnnotationConfigRegistry接口有两个方法,分别对应了注解生成beanDefinition的两种方式
在这里插入图片描述
来到其实现类AnnotationConfigApplicationContext可以发现类里有两个成员变量readerscanner
reader对应register方法(根据传入class生成beanDefinition)
scanner对应scan方法(根据传入包名扫描特定注解表示的class生成beanDefinition)

在这里插入图片描述


先看register方法的实现

AnnotationConfigApplicationContext#register

AnnotationConfigApplicationContext.register(Class<?>... componentClasses)

AnnotatedBeanDefinitionReader#doRegisterBean

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

		//根据bean类生成beanDefinition(实际上就是解析出 AnnotationMetadata 元数据)
		AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);

		//根据condition注解条件判断是否跳过
		if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
			return;
		}

		//创建bean之后的回调方法
		abd.setInstanceSupplier(supplier);

		//设置作用域
		ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
		abd.setScope(scopeMetadata.getScopeName());

		//得到beanName
		String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));

		//通用注解解析:Lazy、Primary、DependsOn、Role、Description
		AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
		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));
				}
			}
		}

		//自定义处理
		if (customizers != null) {
			for (BeanDefinitionCustomizer customizer : customizers) {
				customizer.customize(abd);
			}
		}

		//封装成BeanDefinitionHolder
		BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
		//是否需要代理
		definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
		//注册beanDefinition到registry
		BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
	}
BeanDefinitionRegistry#registerBeanDefinition


进入BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry)方法
在这里插入图片描述
可以发现最终会调用BeanDefinitionRegistry.registerBeanDefinition方法。但这是一个接口,其对应的实现类是哪个呢?
其实就是AnnotationConfigApplicationContext本身。

在赋值reader的时候会把自身传进去赋值给register,而AnnotationConfigApplicationContext继承自GenericApplicationContext,GenericApplicationContext又继承自BeanDefinitionRegistry,所以AnnotationConfigApplicationContext也是一个BeanDefinitionRegistry。

GenericApplicationContext.registerBeanDefinition实际上只是调用了另一个实现类DefaultListableBeanFactory的registerBeanDefinition方法

reader赋值
在这里插入图片描述
在这里插入图片描述
GenericApplicationContext.registerBeanDefinition
在这里插入图片描述
综上最终会来到DefaultListableBeanFactory#registerBeanDefinition,也即BeanDefinitionRegistry#registerBeanDefinition

public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
			throws BeanDefinitionStoreException {

		Assert.hasText(beanName, "Bean name must not be empty");
		Assert.notNull(beanDefinition, "BeanDefinition must not be null");

		//抽象beanDefinition的一些处理(beanDefinition也有继承关系)
		if (beanDefinition instanceof AbstractBeanDefinition) {
			try {
				((AbstractBeanDefinition) beanDefinition).validate();
			}
			catch (BeanDefinitionValidationException ex) {
				throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
						"Validation of bean definition failed", ex);
			}
		}
		//beanName是否已经存在beanDefinition
		BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
		if (existingDefinition != null) {
			//不允许覆盖则报错
			if (!isAllowBeanDefinitionOverriding()) {
				throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
			}
			//打印一些日志
			else if (existingDefinition.getRole() < beanDefinition.getRole()) {
				// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
				if (logger.isInfoEnabled()) {
					logger.info("Overriding user-defined bean definition for bean '" + beanName +
							"' with a framework-generated bean definition: replacing [" +
							existingDefinition + "] with [" + beanDefinition + "]");
				}
			}
			else if (!beanDefinition.equals(existingDefinition)) {
				if (logger.isDebugEnabled()) {
					logger.debug("Overriding bean definition for bean '" + beanName +
							"' with a different definition: replacing [" + existingDefinition +
							"] with [" + beanDefinition + "]");
				}
			}
			else {
				if (logger.isTraceEnabled()) {
					logger.trace("Overriding bean definition for bean '" + beanName +
							"' with an equivalent definition: replacing [" + existingDefinition +
							"] with [" + beanDefinition + "]");
				}
			}
			//覆盖原beanDefinition
			this.beanDefinitionMap.put(beanName, beanDefinition);
		}
		else {
			//判断是否有bean开始注册了,有就加锁保证线程安全
			if (hasBeanCreationStarted()) {
				synchronized (this.beanDefinitionMap) {
					this.beanDefinitionMap.put(beanName, beanDefinition);
					List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
					updatedDefinitions.addAll(this.beanDefinitionNames);
					updatedDefinitions.add(beanName);
					this.beanDefinitionNames = updatedDefinitions;
					removeManualSingletonName(beanName);
				}
			}
			//没有就直接注册beanDefinition
			else {
				this.beanDefinitionMap.put(beanName, beanDefinition);
				this.beanDefinitionNames.add(beanName);
				removeManualSingletonName(beanName);
			}
			this.frozenBeanDefinitionNames = null;
		}

		//如果存在过beanName对应的beanDefinition或者单例bean则重置beanDefinition
		//移除合并的beanDefinition、销毁单例bean、执行MergedBeanDefinitionPostProcessor.resetBeanDefinition
		if (existingDefinition != null || containsSingleton(beanName)) {
			resetBeanDefinition(beanName);
		}
		//如果beanDefinition被冻结的一些处理
		else if (isConfigurationFrozen()) {
			clearByTypeCache();
		}
	}

至此beanDefinition就注册到容器上了。


接下来扫描包的方式即scan方法

AnnotationConfigApplicationContext#scan

在这里插入图片描述

ClassPathBeanDefinitionScanner#doScan

![	protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
		Assert.notEmpty(basePackages, "At least one base package must be specified");
		Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
		for (String basePackage : basePackages) {
			//扫描生成BeanDefinition
			Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
			for (BeanDefinition candidate : candidates) {
				//得到作用域元数据
				ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
				//设置作用域
				candidate.setScope(scopeMetadata.getScopeName());
				//得到beanName
				String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
				if (candidate instanceof AbstractBeanDefinition) {
					postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
				}
				//通用注解解析:Lazy、Primary、DependsOn、Role、Description
				if (candidate instanceof AnnotatedBeanDefinition) {
					AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
				}
				//检测BeanDefinition的beanName是否与其他BeanDefinition存在冲突
				//虽然是一个判断,当时会有三种情况:true:beanName没有冲突,false:有冲突但兼容,抛异常:有冲突且不兼容
				if (checkCandidate(beanName, candidate)) {
					//没有冲突则注册
					BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
					definitionHolder =
							AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
					beanDefinitions.add(definitionHolder);
					//注册beanDefinition
					registerBeanDefinition(definitionHolder, this.registry);
				}
			}
		}
		return beanDefinitions;
	}]
findCandidateComponents

findCandidateComponents方法返回Set < BeanDefinition > 。可以发现当有指定spring.components文件时,会直接用该文件加快加载,否则扫描包下所有资源。
在这里插入图片描述
scanCandidateComponents
这里会先得到包下所有的Resource,再依次获取元数据封装到MetadataReader,当满足excludeFilter/includeFilter/condition条件时,创建ScannedGenericBeanDefinition。

	private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
		Set<BeanDefinition> candidates = new LinkedHashSet<>();
		try {
			String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
					resolveBasePackage(basePackage) + '/' + this.resourcePattern;
			Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
			boolean traceEnabled = logger.isTraceEnabled();
			boolean debugEnabled = logger.isDebugEnabled();
			for (Resource resource : resources) {
				if (traceEnabled) {
					logger.trace("Scanning " + resource);
				}
				try {
					//得到元数据
					MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
					//判断excludeFilter/includeFilter/condition条件
					if (isCandidateComponent(metadataReader)) {
						ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
						sbd.setSource(resource);
						//判断excludeFilter/includeFilter/condition条件
						if (isCandidateComponent(sbd)) {
							if (debugEnabled) {
								logger.debug("Identified candidate component class: " + resource);
							}
							//添加扫描beanDefinition
							candidates.add(sbd);
						}
			//以下都是日志异常处理......
			

isCandidateComponent
在这里插入图片描述

BeanDefinitionRegistry#registerBeanDefinition

进入registerBeanDefinition(definitionHolder, this.registry);
在这里插入图片描述
可以发现最后跟register一样调用BeanDefinitionReaderUtils#registerBeanDefinition进而调用BeanDefinitionRegistry#registerBeanDefinition,这里就不再说一遍了。


XML方式(AbstractXmlApplicationContext)

AbstractXmlApplicationContext#loadBeanDefinitions

在这里插入图片描述
在这里插入图片描述
AbstractXmlApplicationContext会调用BeanDefinitionReader#loadBeanDefinitions加载xml文件,而xml方式具体的实现类就是XmlBeanDefinitionReader。

虽然XmlBeanDefinitionReader和上面提到的AnnotatedBeanDefinitionReader都是以BeanDefinitionReader结尾,但是实际上这两个从类继承来看没有什么关系,并不来自于同一基类也不互相继承。XmlBeanDefinitionReader实现了BeanDefinitionReader接口,而AnnotatedBeanDefinitionReader不实现任何接口也不继承任何类。

跟踪XmlBeanDefinitionReader代码来到真正做事的地方:doLoadBeanDefinitions方法
在这里插入图片描述

XmlBeanDefinitionReader#doLoadBeanDefinitions

在这里插入图片描述
最终来到BeanDefinitionDocumentReader.doRegisterBeanDefinitions()方法

BeanDefinitionDocumentReader#doRegisterBeanDefinitions

这一步主要就是对各种标签的解析
在这里插入图片描述

BeanDefinitionRegistry#registerBeanDefinition

进入bean标签的解析
在这里插入图片描述
可以发现最后同样调用BeanDefinitionReaderUtils#registerBeanDefinition进而调用BeanDefinitionRegistry#registerBeanDefinition,剩下的步骤就跟注解方式的一样了。


总结

注解方式可register直接注册,也可scan扫描注册。register方式通过AnnotatedBeanDefinitionReader创建beanDefinition(同时会得到元数据),再根据元数据等设置完beanDefinition属性后,用BeanDefinitionRegistry注册到容器。scan方式通过ClassPathBeanDefinitionScanner先扫描生成所有的BeanDefinition(同时会得到元数据),依次遍历BeanDefinition,根据元数据等设置BeanDefinition的属性,最后检查是否冲突,当无冲突时也用BeanDefinitionRegistry注册到容器。
xml方式通过XmlBeanDefinitionReader先加载xml文件并封装成document,再将document委托给BeanDefinitionDocumentReader对各种标签进行解析生成beanDefinition,最后用BeanDefinitionRegistry注册到容器中。
可以发现无论是注解register还是注解scan还是xml最终在注册到容器时都会用到BeanDefinitionRegistry,而其具体的实现就是DefaultListableBeanFactory#registerBeanDefinition。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值