【源码】Spring —— BeanDefinition 解读2

前言

本章节想要结合 Spring 中几处使用案例来进一步了解 BeanDefinition

ClassPathScanningCandidateComponentProvider

该类基于类路径扫描获取 BeanDefinition,其构造的 BeanDefinition 实例类型为 ScannedGenericBeanDefinition。不难理解,其内部的元数据基于 SimpleMetadataReader 获取,代码片段如下

	private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
		Set<BeanDefinition> candidates = new LinkedHashSet<>();
		try {
			
			// ...
			
			for (Resource resource : resources) {
				if (traceEnabled) {
					logger.trace("Scanning " + resource);
				}
				if (resource.isReadable()) {
					try {
						MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
						if (isCandidateComponent(metadataReader)) {
							ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
							sbd.setSource(resource);
							
							// ...
							
						}
					}
				}
			}
		}
	}
  • 此处只填充了 source 属性,后续还有基础属性的填充,此处略过,可参考 ClassPathBeanDefinitionScanner
  • 与之相似的还有 AnnotatedBeanDefinitionReader 类,它是基于配置类扫描,注册的 BeanDefinition 类型为 AnnotatedGenericBeanDefinition

ScopedProxyUtils

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

		// 原名
		String originalBeanName = definition.getBeanName();
		
		// 目标 bd
		BeanDefinition targetDefinition = definition.getBeanDefinition();
		// 目标 bd 名称
		String targetBeanName = getTargetBeanName(originalBeanName);

		// 代理 bean 的类型为 ScopedProxyFactoryBean
		// 主要是解决不同作用域实例互相依赖的问题
		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);
		else {
			proxyDefinition.getPropertyValues().add("proxyTargetClass", Boolean.FALSE);
		}
		proxyDefinition.setAutowireCandidate(targetDefinition.isAutowireCandidate());
		proxyDefinition.setPrimary(targetDefinition.isPrimary());
		if (targetDefinition instanceof AbstractBeanDefinition) {
			proxyDefinition.copyQualifiersFrom((AbstractBeanDefinition) targetDefinition);
		}

		// 目标 bd setAutowireCandidate(false) setPrimary(false)
		targetDefinition.setAutowireCandidate(false);
		targetDefinition.setPrimary(false);

		// 先注册目标 bd
		registry.registerBeanDefinition(targetBeanName, targetDefinition);

		// 返回代理 bd holder
		return new BeanDefinitionHolder(proxyDefinition, originalBeanName, definition.getAliases());
	}

这是对需要代理的目标 BeanDefinition 生成代理 BeanDefinition 相关操作,在之前提到的 ClassPathBeanDefinitionScannerAnnotatedGenericBeanDefinition 中都有调用,细节描述:

  • 为目标 BeanDefinition 构造新的名称
  • 构造的代理 BeanDefinition 类型为 RootBeanDefinition,同时指定其 decoratedDefinition resource 属性为目标 BeanDefinition(Holder)
  • 其余部分属性诸如 source role primary 等都是直接复制
  • 特殊处理诸如 propertyValues attribute,维护代理相关标识
  • 处理目标 BeanDefinition 并注册
  • 最后返回代理 BeanDefinitionHolder,后续也会被注册

ConfigurationClassBeanDefinitionReader

该类负责注册由 ConfigurationClassParser 解析配置类后相关的 BeanDefinition,我们重点关注:

  • registerBeanDefinitionForImportedConfigurationClass 方法,注册配置类内部的 普通成员类 或被 Import 的普通类等对应的 BeanDefinition
  • loadBeanDefinitionsForBeanMethod 方法,注册配置类 @Bean 方法对应的 BeanDefinition

registerBeanDefinitionForImportedConfigurationClass

	private void registerBeanDefinitionForImportedConfigurationClass(ConfigurationClass configClass) {
		// 元数据
		AnnotationMetadata metadata = configClass.getMetadata();
		AnnotatedGenericBeanDefinition configBeanDef = new AnnotatedGenericBeanDefinition(metadata);

		// ScopeMetadata 解析
		ScopeMetadata scopeMetadata = scopeMetadataResolver.resolveScopeMetadata(configBeanDef);
		configBeanDef.setScope(scopeMetadata.getScopeName());

		// beanName 解析
		String configBeanName = this.importBeanNameGenerator.generateBeanName(configBeanDef, this.registry);

		// 基于 元数据 解析 DependsOn Primary 等属性
		AnnotationConfigUtils.processCommonDefinitionAnnotations(configBeanDef, metadata);

		BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(configBeanDef, configBeanName);
		// 代理 bd 的构造
		definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
		
		// 注册
		this.registry.registerBeanDefinition(definitionHolder.getBeanName(), definitionHolder.getBeanDefinition());
		configClass.setBeanName(configBeanName);

		if (logger.isTraceEnabled()) {
			logger.trace("Registered bean definition for imported class '" + configBeanName + "'");
		}
	}

方法总结:

  • 对于如上配置类注册的是 AnnotatedGenericBeanDefinition
  • 其注册流程与 AnnotatedBeanDefinitionReader 扫描配置类的流程别无二致:ScopeMetadata 解析、beanName 解析、基于 元数据 的属性解析、代理 BeanDefinition 构造、注册
  • 其中代理 BeanDefinition 的构造流程就是由之前提到的 ScopedProxyUtils 负责

loadBeanDefinitionsForBeanMethod

	private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) {
		ConfigurationClass configClass = beanMethod.getConfigurationClass();
		// 方法元数据
		MethodMetadata metadata = beanMethod.getMetadata();
		String methodName = metadata.getMethodName();

		// Condition 校验
		if (this.conditionEvaluator.shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN)) {
			configClass.skippedBeanMethods.add(methodName);
			return;
		}
		if (configClass.skippedBeanMethods.contains(methodName)) {
			return;
		}

		// 基于 元数据 获取 @Bean 方法的所有属性
		/**
		 * @Bean 注解的相关属性:
		 * name value 会被解析成 beanName
		 * autowire:默认值为 Autowire.NO,即基于注解注入,
		 * 		且该属性已被标注为 @Deprecated
		 * autowireCandidate:是否注入备选 bean,默认 true
		 * initMethod:初始化前方法指定
		 * destroyMethod:销毁方法指定
		 */
		AnnotationAttributes bean = AnnotationConfigUtils.attributesFor(metadata, Bean.class);

		// name 处理
		List<String> names = new ArrayList<>(Arrays.asList(bean.getStringArray("name")));
		String beanName = (!names.isEmpty() ? names.remove(0) : methodName);

		// Register aliases even when overridden
		for (String alias : names) {
			this.registry.registerAlias(beanName, alias);
		}

		// 构造 ConfigurationClassBeanDefinition
		ConfigurationClassBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass, metadata, beanName);
		beanDef.setSource(this.sourceExtractor.extractSource(metadata, configClass.getResource()));

		/**
		 * 此处核心是指定 UniqueFactoryMethodName 为当前方法名
		 */
		if (metadata.isStatic()) {
			// static @Bean method
			if (configClass.getMetadata() instanceof StandardAnnotationMetadata) {
				beanDef.setBeanClass(((StandardAnnotationMetadata) configClass.getMetadata()).getIntrospectedClass());
			}
			else {
				beanDef.setBeanClassName(configClass.getMetadata().getClassName());
			}
			beanDef.setUniqueFactoryMethodName(methodName);
		}
		else {
			beanDef.setFactoryBeanName(configClass.getBeanName());
			beanDef.setUniqueFactoryMethodName(methodName);
		}

		// 指定 ResolvedFactoryMethod
		if (metadata instanceof StandardMethodMetadata) {
			beanDef.setResolvedFactoryMethod(((StandardMethodMetadata) metadata).getIntrospectedMethod());
		}

		// 设置 AutowireMode = AUTOWIRE_CONSTRUCTOR
		beanDef.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);
		beanDef.setAttribute(org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor.
				SKIP_REQUIRED_CHECK_ATTRIBUTE, Boolean.TRUE);

		// Lazy Primary Description 等注解相关解析
		AnnotationConfigUtils.processCommonDefinitionAnnotations(beanDef, metadata);

		// 此处如果指定 AutowireMode 为 byType byName 则进行覆盖
		Autowire autowire = bean.getEnum("autowire");
		if (autowire.isAutowire()) {
			beanDef.setAutowireMode(autowire.value());
		}

		// autowireCandidate 指定,默认 true
		boolean autowireCandidate = bean.getBoolean("autowireCandidate");
		if (!autowireCandidate) {
			beanDef.setAutowireCandidate(false);
		}

		// initMethod 解析
		String initMethodName = bean.getString("initMethod");
		if (StringUtils.hasText(initMethodName)) {
			beanDef.setInitMethodName(initMethodName);
		}

		// destroyMethod 解析
		String destroyMethodName = bean.getString("destroyMethod");
		beanDef.setDestroyMethodName(destroyMethodName);

		// Scope 解析
		ScopedProxyMode proxyMode = ScopedProxyMode.NO;
		AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(metadata, Scope.class);
		if (attributes != null) {
			beanDef.setScope(attributes.getString("value"));
			proxyMode = attributes.getEnum("proxyMode");
			if (proxyMode == ScopedProxyMode.DEFAULT) {
				proxyMode = ScopedProxyMode.NO;
			}
		}

		// 代理相关
		BeanDefinition beanDefToRegister = beanDef;
		if (proxyMode != ScopedProxyMode.NO) {
			BeanDefinitionHolder proxyDef = ScopedProxyCreator.createScopedProxy(
					new BeanDefinitionHolder(beanDef, beanName), this.registry,
					proxyMode == ScopedProxyMode.TARGET_CLASS);
			beanDefToRegister = new ConfigurationClassBeanDefinition(
					(RootBeanDefinition) proxyDef.getBeanDefinition(), configClass, metadata, beanName);
		}

		// 注册
		this.registry.registerBeanDefinition(beanName, beanDefToRegister);
	}
  • 针对 @Bean 方法,构造的是 ConfigurationClassBeanDefinition,它是 AnnotatedBeanDefinition 的实现类
  • 这里的核心是对 factoryMethod 相关处理,@Bean 方法本身被指定为创建目标 bean 的工厂方法,因此针对该类型 bean 的获取最终会被执行该方法
  • 此处会指定 autowireMode = AUTOWIRE_CONSTRUCTOR(工厂方法创建 bean 依赖注入类似于构造方法的依赖注入),因此 @Bean 方法的参数都会作为依赖自动注入
  • @Bean 注解可以指定诸如 autowire initMrthod 等属性,此外若显示指定 autowirebyType byName,则此处会覆盖原本的 AUTOWIRE_CONSTRUCTOR
  • 基于 元数据 的其他属性解析、代理相关等,不再重复叙述

总结

示例中是 Spring 注册 BeanDefinition 的经典案例,在上述收集与注册 BeanDefinition 的行为完成后,容器会在后续的阶段基于这些 BeanDefinition 创建对应的 bean 实例

上一篇:【源码】Spring —— BeanDefinition 解读1

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值