spring深入學習(七)IOC 之解析 bean 標籤:BeanDefinition
解析 bean 標籤的過程其實就是構造一個 BeanDefinition 物件的過程,<bean>
元素標籤擁有的配置屬性,BeanDefinition 均提供了相應的屬性,與之一一對應。所以我們有必要對 BeanDefinition 有一個整體的認識。
BeanDefinition
BeanDefinition 是一個介面,它描述了一個 Bean 例項,包括屬性值、構造方法值和繼承自它的類的更多資訊。它繼承 AttributeAccessor 和 BeanMetadataElement 介面。兩個介面定義如下:
- AttributeAccessor :定義了與其它物件的(元資料)進行連線和訪問的約定,即對屬性的修改,包括獲取、設定、刪除。
- BeanMetadataElement:Bean 元物件持有的配置元素可以通過
getSource()
方法來獲取。
BeanDefinition 整個結構如下圖:
我們常用的三個實現類有:ChildBeanDefinition、GenericBeanDefinition、RootBeanDefinition,三者都繼承 AbstractBeanDefinition。如果配置檔案中定義了父 <bean>
和 子 <bean>
,則父 <bean>
用 RootBeanDefinition表示,子 <bean>
<bean>
的就使用RootBeanDefinition 表示。GenericBeanDefinition 為一站式服務類。AbstractBeanDefinition對三個子類共同的類資訊進行抽象。
解析 Bean 標籤
在 BeanDefinitionParserDelegate.parseBeanDefinitionElement()
中完成 Bean 的解析,返回的是一個已經完成對 <bean>
標籤解析的 BeanDefinition 例項。在該方法內部,首先呼叫 createBeanDefinition()
protected AbstractBeanDefinition createBeanDefinition(@Nullable String className, @Nullable String parentName)
throws ClassNotFoundException {
return BeanDefinitionReaderUtils.createBeanDefinition(
parentName, className, this.readerContext.getBeanClassLoader());
}
委託 BeanDefinitionReaderUtils 建立,如下:
public static AbstractBeanDefinition createBeanDefinition(
@Nullable String parentName, @Nullable String className, @Nullable ClassLoader classLoader) throws ClassNotFoundException {
GenericBeanDefinition bd = new GenericBeanDefinition();
bd.setParentName(parentName);
if (className != null) {
if (classLoader != null) {
bd.setBeanClass(ClassUtils.forName(className, classLoader));
}
else {
bd.setBeanClassName(className);
}
}
return bd;
}
該方法主要是設定 parentName 、className、classLoader。
建立完 GenericBeanDefinition 例項後,再呼叫 parseBeanDefinitionAttributes()
,該方法將建立好的 GenericBeanDefinition 例項當做引數,對 Bean 標籤的所有屬性進行解析,如下:
public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName,
@Nullable BeanDefinition containingBean, AbstractBeanDefinition bd) {
// 解析 scope 標籤
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());
}
// 解析 abstract 標籤
if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) {
bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE)));
}
// 解析 lazy-init 標籤
String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE);
if (DEFAULT_VALUE.equals(lazyInit)) {
lazyInit = this.defaults.getLazyInit();
}
bd.setLazyInit(TRUE_VALUE.equals(lazyInit));
// 解析 autowire 標籤
String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE);
bd.setAutowireMode(getAutowireMode(autowire));
// 解析 depends-on 標籤
if (ele.hasAttribute(DEPENDS_ON_ATTRIBUTE)) {
String dependsOn = ele.getAttribute(DEPENDS_ON_ATTRIBUTE);
bd.setDependsOn(StringUtils.tokenizeToStringArray(dependsOn, MULTI_VALUE_ATTRIBUTE_DELIMITERS));
}
// 解析 autowire-candidate 標籤
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));
}
// 解析 primay 標籤
if (ele.hasAttribute(PRIMARY_ATTRIBUTE)) {
bd.setPrimary(TRUE_VALUE.equals(ele.getAttribute(PRIMARY_ATTRIBUTE)));
}
// 解析 init-method 標籤
if (ele.hasAttribute(INIT_METHOD_ATTRIBUTE)) {
String initMethodName = ele.getAttribute(INIT_METHOD_ATTRIBUTE);
bd.setInitMethodName(initMethodName);
}
else if (this.defaults.getInitMethod() != null) {
bd.setInitMethodName(this.defaults.getInitMethod());
bd.setEnforceInitMethod(false);
}
// 解析 destroy-mothod 標籤
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);
}
// 解析 factory-method 標籤
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;
}
從上面程式碼我們可以清晰地看到對 Bean 標籤屬性的解析,這些屬性我們在工作中都或多或少用到過。
完成 Bean 標籤基本屬性解析後,會依次呼叫 parseMetaElements()
、parseLookupOverrideSubElements()
、parseReplacedMethodSubElements()
對子元素 meta、lookup-method、replace-method 完成解析。下篇博文將會對這三個子元素進行詳細說明。