一、BeanDefinition介绍
BeanDefinition 是一个接口,在 Spring 中存在六种实现:
- AnnotatedGenericBeanDefinition:注解bean
- ChildBeanDefinition:子bean
- ConfigurationClassBeanDefinitionReader.ConfigurationClassBeanDefinition
- GenericBeanDefinition:spring2.5之后代替ChildBeanDefinition和RootBeanDefinition
- RootBeanDefinition:父bean
- ScannedGenericBeanDefinition:扫描bean
BeanDefinition是配置文件<bean>元素标签在容器中的内部表示形式 。<bean>元素标签拥有class、scope、lazy-init等配置属性,AbstractBeanDefinition则提供了相应的beanClass、scope、lazyInit属性,BeanDefinition 和<bean>中的属性是一一对应的 。以上六种实现类都继承了AbstractBeanDefinition,其中 RootBeanDefinition 是最常用的实现类,它对应一般性的<bean>元素标签, GenericBeanDefinition 是自 2.5 版本以后新加入的 bean文件配置属性定义类,是一站式服务类。
在配置文件中可以定义父<bean>和子<bean>,父<bean>用 RootBeanDefinition 表示,而子<bean>用 ChildBeanDefiniton 表示,而没有父<bean> 的<bean>就使用 RootBeanDefinition 表示 。AbstractBeanDefinition 对两者共同的类信息进行抽象。
Spring 通过 BeanDefinition 将配置文件中的<bean>配置信息转换为容器的内部表示,并将
这些 BeanDefiniton 注册到 BeanDefinitonRegistry 中 。 Spring 容器的 BeanDefinitionRegistry 就像
是 Spring 配置信息的内存数据库,主要是以 map 的形式保存,后续操作直接从 BeanDefinitionRegistry 中读取配置信息。
二、目的
从上面BeanDefinition的介绍可以知道,xml中的bean标签对应spring中的一个BeanDefinition( 具体实现为GenericBeanDefinition)实例,bean标签的属性与BeanDefinition中的属性也是一一对应的。在给BeanDefinition的属性设置值时,首先要创建BeanDefinition。创建BeanDefinition的过程,就是我们要分析的重点。先来看下AbstractBeanDefinition类中包含的属性
public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccessor
implements BeanDefinition, Cloneable {
// 省略一些常量
// bean的作用范围,对应bean标签中的scope属性
@Nullable
private String scope = SCOPE_DEFAULT;
// 是否是原型,对应bean标签中的abstract属性
private boolean abstractFlag = false;
// 是否延迟加载,对应bean标签中的lazy-init属性
private boolean lazyInit = false;
// 自动注入模式,对应备案标签中的autowire属性
private int autowireMode = AUTOWIRE_NO;
// 依赖检查
private int dependencyCheck = DEPENDENCY_CHECK_NONE;
// 用来表示一个bean的实例化依靠另一个bean先实例化,对应bean标签的depend-on属性
@Nullable
private String[] dependsOn;
private boolean autowireCandidate = true;
// 自动装配时当出现多个bean候选者时,将作为首选者,对应bean标签的primary属性
private boolean primary = false;
// 用于记录Qualifier,对应子元素qualifier
private final Map<String, AutowireCandidateQualifier> qualifiers = new LinkedHashMap<>(0);
@Nullable
private Supplier<?> instanceSupplier;
// 允许访问非公开的构造器和方法,程序设置
private boolean nonPublicAccessAllowed = true;
// 是否以一种宽松的模式解析构造函数
private boolean lenientConstructorResolution = true;
// 对应bean标签中的factory-bean属性
@Nullable
private String factoryBeanName;
// 对应bean标签中的factory-method属性
@Nullable
private String factoryMethodName;
// 记录构造函数注入属性,对应bean标签的constructor-arg子元素
@Nullable
private ConstructorArgumentValues constructorArgumentValues;
// 普通属性集合
@Nullable
private MutablePropertyValues propertyValues;
// 方法重写的持有者,记录lookup-method、replace-method子元素
@Nullable
private MethodOverrides methodOverrides;
// 初始化方法,对应bean标签中的init-method属性
@Nullable
private String initMethodName;
// 销毁方法,对应bean标签中的destroy-method属性
@Nullable
private String destroyMethodName;
// 是否执行init-method,程序设置
private boolean enforceInitMethod = true;
// 是否执行destroy-method,程序设置
private boolean enforceDestroyMethod = true;
// 是否是用户定义的而不是应用程序本身定义的,创建AOP时候为true,程序设置
private boolean synthetic = false;
private int role = BeanDefinition.ROLE_APPLICATION;
// bean的描述信息
@Nullable
private String description;
// 这个bean定义的资源
@Nullable
private Resource resource;
}
三、相关类
- org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader:解析xml标签的入口
- org.springframework.beans.factory.xml.BeanDefinitionParserDelegate:解析bean标签
- org.springframework.beans.factory.support.BeanDefinitionReaderUtils:创建BeanDefinition
四、源码分析
-
根据标签的命名空间(namespace)和标签名称来选择对应的处理方法。
1.1 根据命名空间,选择对应的处理方法
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) { 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; // 默认标签的命名空间为:http://www.springframework.org/schema/beans if (delegate.isDefaultNamespace(ele)) { // 解析默认标签 parseDefaultElement(ele, delegate); } else { // 解析自定义标签 delegate.parseCustomElement(ele); } } } } else { delegate.parseCustomElement(root); } }spring在解析xml的时候,把标签分为两类:默认标签和扩展标签。
默认标签<bean id="person1" class="com.kaka.spring.beans.Person"/>扩展标签
<tx:annotaition-driven/>1.2 根据标签的名称,选择对应的处理方法
// 默认标签解析 private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) { if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) { // 对import标签的处理 importBeanDefinitionResource(ele); } else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) { // 处理alias标签 processAliasRegistration(ele); } else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) { // 处理bean标签(本章主要分析这个) processBeanDefinition(ele, delegate); } else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) { // 递归(recurse)处理beans标签 doRegisterBeanDefinitions(ele); } } -
处理bean标签的大致步骤(还在DefaultBeanDefinitionDocumentReader这个类中)
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
// 1.解析bean标签,获取bdHolder实例(本章主要分析这个)
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
// 2.装饰bdHolder
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// 3.注册装饰后的实例
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" +
bdHolder.getBeanName() + "'", ele, ex);
}
// 4.发布注册事件,通知相关监听器
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
- 交由BeanDefinitionParserDelegate这个类,去处理bean标签,最终获取一个BeanDefinitionHolder实例。
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {
return parseBeanDefinitionElement(ele, null);
}
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
// 解析id属性
String id = ele.getAttribute(ID_ATTRIBUTE);
// 解析name属性
String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
List<String> aliases = new ArrayList<>();
if (StringUtils.hasLength(nameAttr)) {
String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
aliases.addAll(Arrays.asList(nameArr));
}
String beanName = id;
if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
beanName = aliases.remove(0);
if (logger.isDebugEnabled()) {
logger.debug("No XML 'id' specified - using '" + beanName +
"' as bean name and " + aliases + " as aliases");
}
}
if (containingBean == null) {
checkNameUniqueness(beanName, aliases, ele);
}
// 解析bean标签的其他属性,并封装至beanDefinition。这儿就是本章分析的重点,点进去
AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
if (beanDefinition != null) {
if (!StringUtils.hasText(beanName)) {
try {
if (containingBean != null) {
beanName = BeanDefinitionReaderUtils.generateBeanName(
beanDefinition, this.readerContext.getRegistry(), true);
}
else {
beanName = this.readerContext.generateBeanName(beanDefinition);
// Register an alias for the plain bean class name, if still possible,
// if the generator returned the class name plus a suffix.
// This is expected for Spring 1.2/2.0 backwards compatibility.
String beanClassName = beanDefinition.getBeanClassName();
if (beanClassName != null &&
beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
!this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
aliases.add(beanClassName);
}
}
if (logger.isDebugEnabled()) {
logger.debug("Neither XML 'id' nor 'name' specified - " +
"using generated bean name [" + beanName + "]");
}
}
catch (Exception ex) {
error(ex.getMessage(), ele);
return null;
}
}
String[] aliasesArray = StringUtils.toStringArray(aliases);
// 将获取到的信息封装到BeanDefinitionHolder实例中
return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
}
return null;
}
//解析bean标签的其他属性
public AbstractBeanDefinition parseBeanDefinitionElement(
Element ele, String beanName, @Nullable BeanDefinition containingBean) {
this.parseState.push(new BeanEntry(beanName));
// 解析class属性
String className = null;
if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
}
// 解析parent属性
String parent = null;
if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
parent = ele.getAttribute(PARENT_ATTRIBUTE);
}
try {
// 创建用于承载属性的 AbstractBeanDefinition 类型的 GenericBeanDefinition,点进去
AbstractBeanDefinition bd = createBeanDefinition(className, parent);
// 硬编码解析默认bean的各种属性
parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
// 提取 descripτion
bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
// 解析元数据
parseMetaElements(ele, bd);
// 解析lookup-method 属性
parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
// 解析replaced-method 属性
parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
// 解析构造函数参数
parseConstructorArgElements(ele, bd);
// 解析property子元素
parsePropertyElements(ele, bd);
// 解析qualifier子元素
parseQualifierElements(ele, bd);
bd.setResource(this.readerContext.getResource());
bd.setSource(extractSource(ele));
return bd;
}
catch (ClassNotFoundException ex) {
error("Bean class [" + className + "] not found", ele, ex);
}
catch (NoClassDefFoundError err) {
error("Class that bean class [" + className + "] depends on not found", ele, err);
}
catch (Throwable ex) {
error("Unexpected failure during bean definition parsing", ele, ex);
}
finally {
this.parseState.pop();
}
return null;
}
protected AbstractBeanDefinition createBeanDefinition(@Nullable String className, @Nullable String parentName)
throws ClassNotFoundException {
// 交由BeanDefinitionReaderUtils创建AbstractBeanDefinition
return BeanDefinitionReaderUtils.createBeanDefinition(
parentName, className, this.readerContext.getBeanClassLoader());
}
- 使用BeanDefinitionReaderUtils创建AbstractBeanDefinition
public static AbstractBeanDefinition createBeanDefinition(
@Nullable String parentName, @Nullable String className, @Nullable ClassLoader classLoader) throws ClassNotFoundException {
// 创建GenericBeanDefinition
GenericBeanDefinition bd = new GenericBeanDefinition();
bd.setParentName(parentName);
if (className != null) {
if (classLoader != null) {
// 如果classLoader不为空,则使用该classLoader加载该类对象,否则只记录className
// ClassUtils中反射的类实例是缓存起来的,不是每次都反射获取
bd.setBeanClass(ClassUtils.forName(className, classLoader));
}
else {
bd.setBeanClassName(className);
}
}
return bd;
}
经过上面这个步骤,就创建出了一个GenericBeanDefinition实例,并给其parentName、beanClass和beanClassName三个属性设置了值。
五、总结
- DefaultBeanDefinitionDocumentReader根据标签的命名空间和标签名称选择对应的处理方法,bean标签的整体处理过程是在DefaultBeanDefinitionDocumentReader#processBeanDefinition()方法中完成的。
- 处理bean标签的第一步,需要获取BeanDefinitionHolder实例,该实例由BeanDefinitionParserDelegate创建。
- BeanDefinitionHolder的创建需要包含一个BeanDefinition实例,这个BeanDefinition实例由BeanDefinitionReaderUtils创建。
- BeanDefinition实例创建完成之后,其各个属性的赋值是由BeanDefinitionParserDelegate#parseBeanDefinitionElement()方法完成。
本文详细解析了Spring框架中BeanDefinition的六种实现及其作用,包括AnnotatedGenericBeanDefinition、ChildBeanDefinition等。介绍了BeanDefinition在Spring配置文件中的角色及其实现类之间的关系,以及BeanDefinition的创建和属性赋值过程。

5240

被折叠的 条评论
为什么被折叠?



