Spring中Bean的定义对象,由以下接口BeanDefinition来定义,其代码如下:
http://www.easysb.cn/2019/04/275.html
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
/**
* Scope identifier for the standard singleton scope: "singleton".
* <p>Note that extended bean factories might support further scopes.
* @see #setScope
*/
String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
/**
* Scope identifier for the standard prototype scope: "prototype".
* <p>Note that extended bean factories might support further scopes.
* @see #setScope
*/
String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;
/**
* Role hint indicating that a {@code BeanDefinition} is a major part
* of the application. Typically corresponds to a user-defined bean.
*/
int ROLE_APPLICATION = 0;
/**
* Role hint indicating that a {@code BeanDefinition} is a supporting
* part of some larger configuration, typically an outer
* {@link org.springframework.beans.factory.parsing.ComponentDefinition}.
* {@code SUPPORT} beans are considered important enough to be aware
* of when looking more closely at a particular
* {@link org.springframework.beans.factory.parsing.ComponentDefinition},
* but not when looking at the overall configuration of an application.
*/
int ROLE_SUPPORT = 1;
/**
* Role hint indicating that a {@code BeanDefinition} is providing an
* entirely background role and has no relevance to the end-user. This hint is
* used when registering beans that are completely part of the internal workings
* of a {@link org.springframework.beans.factory.parsing.ComponentDefinition}.
*/
int ROLE_INFRASTRUCTURE = 2;
/**
* Return the name of the parent definition of this bean definition, if any.
*/
String getParentName();
/**
* Set the name of the parent definition of this bean definition, if any.
*/
void setParentName(String parentName);
/**
* Return the current bean class name of this bean definition.
* <p>Note that this does not have to be the actual class name used at runtime, in
* case of a child definition overriding/inheriting the class name from its parent.
* Hence, do <i>not</i> consider this to be the definitive bean type at runtime but
* rather only use it for parsing purposes at the individual bean definition level.
*/
String getBeanClassName();
/**
* Override the bean class name of this bean definition.
* <p>The class name can be modified during bean factory post-processing,
* typically replacing the original class name with a parsed variant of it.
*/
void setBeanClassName(String beanClassName);
/**
* Return the factory bean name, if any.
*/
String getFactoryBeanName();
/**
* Specify the factory bean to use, if any.
*/
void setFactoryBeanName(String factoryBeanName);
/**
* Return a factory method, if any.
*/
String getFactoryMethodName();
/**
* Specify a factory method, if any. This method will be invoked with
* constructor arguments, or with no arguments if none are specified.
* The method will be invoked on the specified factory bean, if any,
* or otherwise as a static method on the local bean class.
* @param factoryMethodName static factory method name,
* or {@code null} if normal constructor creation should be used
* @see #getBeanClassName()
*/
void setFactoryMethodName(String factoryMethodName);
/**
* Return the name of the current target scope for this bean,
* or {@code null} if not known yet.
*/
String getScope();
/**
* Override the target scope of this bean, specifying a new scope name.
* @see #SCOPE_SINGLETON
* @see #SCOPE_PROTOTYPE
*/
void setScope(String scope);
/**
* Return whether this bean should be lazily initialized, i.e. not
* eagerly instantiated on startup. Only applicable to a singleton bean.
*/
boolean isLazyInit();
/**
* Set whether this bean should be lazily initialized.
* <p>If {@code false}, the bean will get instantiated on startup by bean
* factories that perform eager initialization of singletons.
*/
void setLazyInit(boolean lazyInit);
/**
* Return the bean names that this bean depends on.
*/
String[] getDependsOn();
/**
* Set the names of the beans that this bean depends on being initialized.
* The bean factory will guarantee that these beans get initialized first.
*/
void setDependsOn(String... dependsOn);
/**
* Return whether this bean is a candidate for getting autowired into some other bean.
*/
boolean isAutowireCandidate();
/**
* Set whether this bean is a candidate for getting autowired into some other bean.
*/
void setAutowireCandidate(boolean autowireCandidate);
/**
* Return whether this bean is a primary autowire candidate.
* If this value is true for exactly one bean among multiple
* matching candidates, it will serve as a tie-breaker.
*/
boolean isPrimary();
/**
* Set whether this bean is a primary autowire candidate.
* <p>If this value is true for exactly one bean among multiple
* matching candidates, it will serve as a tie-breaker.
*/
void setPrimary(boolean primary);
/**
* Return the constructor argument values for this bean.
* <p>The returned instance can be modified during bean factory post-processing.
* @return the ConstructorArgumentValues object (never {@code null})
*/
ConstructorArgumentValues getConstructorArgumentValues();
/**
* Return the property values to be applied to a new instance of the bean.
* <p>The returned instance can be modified during bean factory post-processing.
* @return the MutablePropertyValues object (never {@code null})
*/
MutablePropertyValues getPropertyValues();
/**
* Return whether this a <b>Singleton</b>, with a single, shared instance
* returned on all calls.
* @see #SCOPE_SINGLETON
*/
boolean isSingleton();
/**
* Return whether this a <b>Prototype</b>, with an independent instance
* returned for each call.
* @see #SCOPE_PROTOTYPE
*/
boolean isPrototype();
/**
* Return whether this bean is "abstract", that is, not meant to be instantiated.
*/
boolean isAbstract();
/**
* Get the role hint for this {@code BeanDefinition}. The role hint
* provides the frameworks as well as tools with an indication of
* the role and importance of a particular {@code BeanDefinition}.
* @see #ROLE_APPLICATION
* @see #ROLE_SUPPORT
* @see #ROLE_INFRASTRUCTURE
*/
int getRole();
/**
* Return a human-readable description of this bean definition.
*/
String getDescription();
/**
* Return a description of the resource that this bean definition
* came from (for the purpose of showing context in case of errors).
*/
String getResourceDescription();
/**
* Return the originating BeanDefinition, or {@code null} if none.
* Allows for retrieving the decorated bean definition, if any.
* <p>Note that this method returns the immediate originator. Iterate through the
* originator chain to find the original BeanDefinition as defined by the user.
*/
BeanDefinition getOriginatingBeanDefinition();
}
Bean的XML配置等多种形式,都会由 BeanDefinitionParserDelegate.parseBeanDefinitionElement
进行解析,其流程如下:
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {
return parseBeanDefinitionElement(ele, null);
}
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
// 获取id属性
String id = ele.getAttribute(ID_ATTRIBUTE);
// 获取name属性
String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
List<String> aliases = new ArrayList<String>();
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()) {
// 如果没有id属性,则以第一个别名作为id本命
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) {
如果没有子bean直接检测本名、别名是否有重复
checkNameUniqueness(beanName, aliases, ele);
}
// 对Bean的更多属性进行解析
AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
if (beanDefinition != null) {
// 如果bean没有定义id,name
if (!StringUtils.hasText(beanName)) {
try {
if (containingBean != null) {
// 假如包含子bean,那么会生成一个唯一name
beanName = BeanDefinitionReaderUtils.generateBeanName(
beanDefinition, this.readerContext.getRegistry(), true);
}
else {
// 如果不包含子bean,则由context来生成唯一name
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)) {
// 向上兼容,增加对应的class名字别名
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);
// 构建一个包含bean定义的holder对象
return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
}
return null;
}
上面的检测本名、别名的唯一性的函数 checkNameUniqueness
实现如下,
protected void checkNameUniqueness(String beanName, List<String> aliases, Element beanElement) {
String foundName = null;
// 检查本名是否冲突
if (StringUtils.hasText(beanName) && this.usedNames.contains(beanName)) {
foundName = beanName;
}
// 检查别名是否冲突
if (foundName == null) {
foundName = CollectionUtils.findFirstMatch(this.usedNames, aliases);
}
if (foundName != null) {
error("Bean name '" + foundName + "' is already used in this <beans> element", beanElement);
}
// 如果没有冲突则直接将现有的加入到集合中
this.usedNames.add(beanName);
this.usedNames.addAll(aliases);
}
接下来再详细了解下 parseBeanDefinitionElement
是如何将DOM元素解析成Bean的定义对象的:
public AbstractBeanDefinition parseBeanDefinitionElement(
Element ele, String beanName, BeanDefinition containingBean) {
// 记录解析的对象本名
this.parseState.push(new BeanEntry(beanName));
String className = null;
// 解析是否含有class属性,记录类名
if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
}
try {
String parent = null;
// 解析是否含有parent属性,记录下来
if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
parent = ele.getAttribute(PARENT_ATTRIBUTE);
}
// 根据类名和父bean构建一个bean定义结构对象
AbstractBeanDefinition bd = createBeanDefinition(className, parent);
// 解析Bean的其他定义的属性
parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
// 获取bean的description描述信息
bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
// 对meta属性进行解析
parseMetaElements(ele, bd);
// 对lookup-method属性解析
parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
// 对replace-method属性解析
parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
// 解析构造函数的参数
parseConstructorArgElements(ele, bd);
// 解析成员属性
parsePropertyElements(ele, bd);
// 解析qulifier属性
parseQualifierElements(ele, bd);
// 设置当前bean定义结构的生成的数据来源信息
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;
}
parseBeanDefinitionAttributes
是解析Bean定义的各种属性的,请实现如下:
/**
* Apply the attributes of the given bean element to the given bean * definition.
* @param ele bean declaration element
* @param beanName bean name
* @param containingBean containing bean definition
* @return a bean definition initialized according to the bean element attributes
*/
public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName,
BeanDefinition containingBean, AbstractBeanDefinition bd) {
if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) {
error("Old 1.x 'singleton' attribute in use - upgrade to 'scope' declaration", ele);
}
else if (ele.hasAttribute(SCOPE_ATTRIBUTE)) {
bd.setScope(ele.getAttribute(SCOPE_ATTRIBUTE));
}
else if (containingBean != null) {
// Take default from containing bean in case of an inner bean definition.
bd.setScope(containingBean.getScope());
}
if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) {
bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE)));
}
String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE);
if (DEFAULT_VALUE.equals(lazyInit)) {
lazyInit = this.defaults.getLazyInit();
}
bd.setLazyInit(TRUE_VALUE.equals(lazyInit));
String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE);
bd.setAutowireMode(getAutowireMode(autowire));
String dependencyCheck = ele.getAttribute(DEPENDENCY_CHECK_ATTRIBUTE);
bd.setDependencyCheck(getDependencyCheck(dependencyCheck));
if (ele.hasAttribute(DEPENDS_ON_ATTRIBUTE)) {
String dependsOn = ele.getAttribute(DEPENDS_ON_ATTRIBUTE);
bd.setDependsOn(StringUtils.tokenizeToStringArray(dependsOn, MULTI_VALUE_ATTRIBUTE_DELIMITERS));
}
String autowireCandidate = ele.getAttribute(AUTOWIRE_CANDIDATE_ATTRIBUTE);
if ("".equals(autowireCandidate) || DEFAULT_VALUE.equals(autowireCandidate)) {
String candidatePattern = this.defaults.getAutowireCandidates();
if (candidatePattern != null) {
String[] patterns = StringUtils.commaDelimitedListToStringArray(candidatePattern);
bd.setAutowireCandidate(PatternMatchUtils.simpleMatch(patterns, beanName));
}
}
else {
bd.setAutowireCandidate(TRUE_VALUE.equals(autowireCandidate));
}
if (ele.hasAttribute(PRIMARY_ATTRIBUTE)) {
bd.setPrimary(TRUE_VALUE.equals(ele.getAttribute(PRIMARY_ATTRIBUTE)));
}
if (ele.hasAttribute(INIT_METHOD_ATTRIBUTE)) {
String initMethodName = ele.getAttribute(INIT_METHOD_ATTRIBUTE);
if (!"".equals(initMethodName)) {
bd.setInitMethodName(initMethodName);
}
}
else {
if (this.defaults.getInitMethod() != null) {
bd.setInitMethodName(this.defaults.getInitMethod());
bd.setEnforceInitMethod(false);
}
}
if (ele.hasAttribute(DESTROY_METHOD_ATTRIBUTE)) {
String destroyMethodName = ele.getAttribute(DESTROY_METHOD_ATTRIBUTE);
bd.setDestroyMethodName(destroyMethodName);
}
else {
if (this.defaults.getDestroyMethod() != null) {
bd.setDestroyMethodName(this.defaults.getDestroyMethod());
bd.setEnforceDestroyMethod(false);
}
}
if (ele.hasAttribute(FACTORY_METHOD_ATTRIBUTE)) {
bd.setFactoryMethodName(ele.getAttribute(FACTORY_METHOD_ATTRIBUTE));
}
if (ele.hasAttribute(FACTORY_BEAN_ATTRIBUTE)) {
bd.setFactoryBeanName(ele.getAttribute(FACTORY_BEAN_ATTRIBUTE));
}
return bd;
}
parseMetaElements
是用来解析meta属性,解析出所有的key->value属性值对,其实现如下:
public void parseMetaElements(Element ele, BeanMetadataAttributeAccessor attributeAccessor) {
NodeList nl = ele.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (isCandidateElement(node) && nodeNameEquals(node, META_ELEMENT)) {
Element metaElement = (Element) node;
// 获取key属性和value属性值
String key = metaElement.getAttribute(KEY_ATTRIBUTE);
String value = metaElement.getAttribute(VALUE_ATTRIBUTE);
BeanMetadataAttribute attribute = new BeanMetadataAttribute(key, value);
attribute.setSource(extractSource(metaElement));
attributeAccessor.addMetadataAttribute(attribute);
}
}
}
parseLookupOverrideSubElements
解析所有的lookup-method属性,其实现如下:
public void parseLookupOverrideSubElements(Element beanEle, MethodOverrides overrides) {
NodeList nl = beanEle.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (isCandidateElement(node) && nodeNameEquals(node, LOOKUP_METHOD_ELEMENT)) {
Element ele = (Element) node;
String methodName = ele.getAttribute(NAME_ATTRIBUTE);
String beanRef = ele.getAttribute(BEAN_ELEMENT);
LookupOverride override = new LookupOverride(methodName, beanRef);
override.setSource(extractSource(ele));
overrides.addOverride(override);
}
}
}
parseReplacedMethodSubElements
解析所有的replaced-method属性,其实现如下:
public void parseReplacedMethodSubElements(Element beanEle, MethodOverrides overrides) {
NodeList nl = beanEle.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (isCandidateElement(node) && nodeNameEquals(node, REPLACED_METHOD_ELEMENT)) {
Element replacedMethodEle = (Element) node;
String name = replacedMethodEle.getAttribute(NAME_ATTRIBUTE);
String callback = replacedMethodEle.getAttribute(REPLACER_ATTRIBUTE);
ReplaceOverride replaceOverride = new ReplaceOverride(name, callback);
// Look for arg-type match elements.
List<Element> argTypeEles = DomUtils.getChildElementsByTagName(replacedMethodEle, ARG_TYPE_ELEMENT);
for (Element argTypeEle : argTypeEles) {
String match = argTypeEle.getAttribute(ARG_TYPE_MATCH_ATTRIBUTE);
match = (StringUtils.hasText(match) ? match : DomUtils.getTextValue(argTypeEle));
if (StringUtils.hasText(match)) {
replaceOverride.addTypeIdentifier(match);
}
}
replaceOverride.setSource(extractSource(replacedMethodEle));
overrides.addOverride(replaceOverride);
}
}
}
parseConstructorArgElements
是解析constructor-arg构造函数的参数信息,其实现如下:
public void parseConstructorArgElements(Element beanEle, BeanDefinition bd) {
NodeList nl = beanEle.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (isCandidateElement(node) && nodeNameEquals(node, CONSTRUCTOR_ARG_ELEMENT)) {
parseConstructorArgElement((Element) node, bd);
}
}
}
parsePropertyElements
是解析property属性,其实现如下:
public void parsePropertyElements(Element beanEle, BeanDefinition bd) {
NodeList nl = beanEle.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (isCandidateElement(node) && nodeNameEquals(node, PROPERTY_ELEMENT)) {
parsePropertyElement((Element) node, bd);
}
}
}
parseQualifierElements
是解析qualifier属性,其实现如下:
public void parseQualifierElements(Element beanEle, AbstractBeanDefinition bd) {
NodeList nl = beanEle.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (isCandidateElement(node) && nodeNameEquals(node, QUALIFIER_ELEMENT)) {
parseQualifierElement((Element) node, bd);
}
}
}
至此,我们可以差不多了解都配置文件由相应的Reader读取后解析成DOM对象后,会由 BeanDefinitionParserDelegate
解析成Bean定义结构对象,为后续的Bean的生成提供了数据源参考。