Spring的BeanDefinition

Spring IOC容器管理着一个或多个bean。这些bean是使用用户提供给容器的配置元数据创建的,例如XML配置、@Bean注解等方式。
在容器本身内,这些bean定义表示为BeanDefinition 对象。

BeanDefiniton——Bean的元信息

BeanDefiniton元信息

BeanDefinition的注册

  1. XML配置元信息:<bean>标签
  2. Java注解配置元信息:@Bean、@Component、@Import
  3. Java API配置元信息:
    - BeanDefinitionRegistry.registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
    - BeanDefinitionReaderUtils.registerWithGeneratedName(AbstractBeanDefinition definition, BeanDefinitionRegistry registry)
    - AnnotatedBeanDefinitionReader.registerBean(Class<?> annotatedClass)
  4. 将外部对象注册为Bean:SingletonBeanRegistry.registerSingleton(String beanName, Object singletonObject)

注解方式注册BeanDefinition源码分析

我们从BeanDefinition中也可以看出,这个接口的主要作用更多的是描述一个Bean,就像最开始我们通过XML配置一个Bean一样,Bean的全类名、名称、作用域、是否依赖注入,是否延迟加载等等属性,都在BeanDefinition中可以找到与之对应的属性,因此我们就可以推断,其实我们配置的Bean信息就保存在一个BeanDefinition对象之中。
由于现在企业开发中,大多使用的是注解@Bean的形式来构建对象,因此我选择AnnotationConfigWebApplicationContext类来分析,BeanDefinition是如何创建并生成Bean对象的。
我们找到容器启动的过程中处理BeanDefinition的代码AbstractApplicationContext.refresh()方法(容器启动过程请参考我的这一篇关于容器的文章Spring与IOC容器

// AbstractApplicationContext.refresh()方法中的这一行就是创建BeanDefinition的
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
	//初始化BeanFactory,并进行xml读取或注解扫描,并将得到的BeanFactory记录在当前实体的属性中
	refreshBeanFactory();
	//返回当前实体的beanFactory属性
	return getBeanFactory();
}

我们发现关键的refreshBeanFactory()方法在AbstractApplicationContext类中是一个抽象方法,需要子类去进行实现,然后我我们点到它的实现类AbstractRefreshableApplicationContext中,看具体的实现逻辑:

	@Override
	protected final void refreshBeanFactory() throws BeansException {
		if (hasBeanFactory()) {
			destroyBeans();
			closeBeanFactory();
		}
		try {
			//创建DefaultListableBeanFactory实例,因为它是容器的基础,必须要先被实例化
			DefaultListableBeanFactory beanFactory = createBeanFactory();
			//为了序列化指定id,如有需要,使得这个BeanFactory从id反序列化到BeanFactory对象
			beanFactory.setSerializationId(getId());
			//定制beanFactory,设置相关属性,包括是否允许覆盖同名称的不同定义的对象、是否允许bean之间存在循环依赖
			customizeBeanFactory(beanFactory);
			//初始化DocumentReader,并进行XML文件或注解的读取及解析
			loadBeanDefinitions(beanFactory);
			//使用全局变量beanFactory记录DefaultListableBeanFactory实例
			synchronized (this.beanFactoryMonitor) {
				this.beanFactory = beanFactory;
			}
		}
		catch (IOException ex) {
			throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
		}
	}

从翻译的注释中,我们知道要看的是loadBeanDefinitions()这个方法,由于它又是一个抽象的方法,而且我们这里要分析注解的实现,所以我就选择了AnnotationConfigWebApplicationContext这个类的实现
在这里插入图片描述
进入loadBeanDefinitions()方法的前两行,就得到了两个对象,分别是处理@Bean和XML的<bean>标签

AnnotatedBeanDefinitionReader reader = getAnnotatedBeanDefinitionReader(beanFactory);
ClassPathBeanDefinitionScanner scanner = getClassPathBeanDefinitionScanner(beanFactory);

我们这里只看AnnotatedBeanDefinitionReader的register()方法,一路从调用链点到doRegisterBean()方法

<T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,
			@Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {
		// 先声明一个AnnotatedGenericBeanDefinition对象,用于后面进行注册
		AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
		// 校验是否需要注册这个bean,如果没有被@Conditional注解修饰,直接返回false
		if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
			return;
		}
		abd.setInstanceSupplier(instanceSupplier);
		ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
		abd.setScope(scopeMetadata.getScopeName());
		// 生成bean的名字
		String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
		// 设置BeanDefinition的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));
				}
			}
		}
		for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
			customizer.customize(abd);
		}
		// BeanDefinitionHolder就是一个BeanDefinition的持有者,持有BeanDefinition的名字和引用
		BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
		// 为提供的目标bean生成一个作用域代理
		definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
		// 注册给定的definition
		BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
	}

具体的注册逻辑registerBeanDefinition()很简单,由于AnnotationConfigApplicationContext持有的BeanDefinitionRegistry对象是DefaultListableBeanFactory,因此就看它的registerBeanDefinition()实现即可,内部逻辑也比较简单,主要就是看这个BeanDefinition是否有注册过,然后放入BeanFactory维护的一个ConcurrentHashMap,以供后续使用。

BeanDefinition的命名

DefaultBeanNameGenerator

由Spring Framework 2.0.3引入,是BeanNameGenerator的默认实现。
关于XML的解析,请根据个人兴趣看一下AbstractXmlApplicationContext.loadBeanDefinitions()方法,然后从XmlBeanDefinitionReader.loadBeanDefinitions(Resource resource)方法看注册BeanDefinitionBeanDefinition的逻辑,从DefaultBeanDefinitionDocumentReader.doRegisterBeanDefinitions(Element root)方法看具体从XML中解析标签注册的逻辑

protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
		// 校验root节点的namespaceURI 不为空 且为 http://www.springframework.org/schema/beans
		if (delegate.isDefaultNamespace(root)) {
			// 获取所有的子节点
			NodeList nl = root.getChildNodes();
			for (int i = 0; i < nl.getLength(); i++) {
				Node node = nl.item(i);
				if (node instanceof Element) {
					Element ele = (Element) node;
					if (delegate.isDefaultNamespace(ele)) {
						// 解析默认标签--<import>、<alias>、<bean>、<beans>
						parseDefaultElement(ele, delegate);
					} else {
						// 解析自定义标签(<aop:config>并不是默认的Namespace,因此Aop在此解析)
						delegate.parseCustomElement(ele);
					}
				}
			}
		} else {
			// 解析自定义标签
			delegate.parseCustomElement(root);
		}
	}
	// 解析默认标签方法逻辑
	private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
		//对<import>进行解析
		if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
			importBeanDefinitionResource(ele);
		}
		//对<alias>进行解析
		else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
			processAliasRegistration(ele);
		}
		//对<bean>进行解析
		else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
			processBeanDefinition(ele, delegate);
		}
		//对<beans>进行解析
		else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
			// recurse
			doRegisterBeanDefinitions(ele);
		}
	}

AnnotationBeanNameGenerator

由Spring Framework 2.5引入,基于注解扫描的BeanNameGenerator实现。

	public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
		// 如果是基于注解的BeanDefinition
		if (definition instanceof AnnotatedBeanDefinition) {
			// 根据注解中的BeanName决定bean名称
			String beanName = determineBeanNameFromAnnotation((AnnotatedBeanDefinition) definition);
			if (StringUtils.hasText(beanName)) {
				// Explicit bean name found.
				return beanName;
			}
		}
		// 如果注解中没有给定BeanDefinition的名称,生成一个默认的唯一BeanName
		return buildDefaultBeanName(definition, registry);
	}
	// 通过注解的方式生成BeanDefinition名称
	protected String determineBeanNameFromAnnotation(AnnotatedBeanDefinition annotatedDef) {
		AnnotationMetadata amd = annotatedDef.getMetadata();
		Set<String> types = amd.getAnnotationTypes();
		String beanName = null;
		for (String type : types) {
			AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(amd, type);
			// 如果注解类型是@Component、@ManagedBean、@Named,并且注解中包含value属性
			if (attributes != null && isStereotypeWithNameValue(type, amd.getMetaAnnotationTypes(type), attributes)) {
				Object value = attributes.get("value");
				if (value instanceof String) {
					String strVal = (String) value;
					if (StringUtils.hasLength(strVal)) {
						// 校验多个注解修饰一个Bean,却有不同Bean名称的情况
						if (beanName != null && !strVal.equals(beanName)) {
							throw new IllegalStateException("Stereotype annotations suggest inconsistent " +
									"component names: '" + beanName + "' versus '" + strVal + "'");
						}
						beanName = strVal;
					}
				}
			}
		}
		return beanName;
	}
	// 没有通过注解指定名称,生成唯一的BeanDefinition名称
	protected String buildDefaultBeanName(BeanDefinition definition) {
		String beanClassName = definition.getBeanClassName();
		Assert.state(beanClassName != null, "No bean class name set");
		String shortClassName = ClassUtils.getShortName(beanClassName);
		// 将一个字符串的首字母大写转为小写,若是"URL"这种字符串,连续多个大写字母开头的,则保持不变
		return Introspector.decapitalize(shortClassName);
	}
	public static String getShortName(String className) {
		// 如果是一个内部类的Bean,传入的className为com.durp.study.OutterClass$InnerClass
		Assert.hasLength(className, "Class name must not be empty");
		int lastDotIndex = className.lastIndexOf(PACKAGE_SEPARATOR);
		// 判断是否是CGLIB的Bean的处理逻辑
		int nameEndIndex = className.indexOf(CGLIB_CLASS_SEPARATOR);
		if (nameEndIndex == -1) {
			nameEndIndex = className.length();
		}
		String shortName = className.substring(lastDotIndex + 1, nameEndIndex);
		// 将$替换为.
		// 最终输出为OutterClass.InnerClass
		shortName = shortName.replace(INNER_CLASS_SEPARATOR, PACKAGE_SEPARATOR);
		return shortName;
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值