IOC之解析bean标签:BeanDefinition
本文作者:chenssy
出处:http://cmsblogs.com/?p=2736
在学习Spring源码
的过程中发现的好站+好贴,感谢作者。Spring版本:Spring 5.0.6.RELEASE
BeanDefinition BeanDefinition
是一个接口,它描述了一个 Bean
实例,包括属性值、构造方法值和继承自它的类的更多信息。
代码如下:
public interface BeanDefinition extends AttributeAccessor , BeanMetadataElement { String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON; String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE; int ROLE_APPLICATION = 0 ; int ROLE_SUPPORT = 1 ; int ROLE_INFRASTRUCTURE = 2 ; void setParentName (@Nullable String parentName) ; @Nullable String getParentName () ; void setBeanClassName (@Nullable String beanClassName) ; @Nullable String getBeanClassName () ; void setScope (@Nullable String scope) ; @Nullable String getScope () ; void setLazyInit (boolean lazyInit) ; boolean isLazyInit () ; void setDependsOn (@Nullable String... dependsOn) ; @Nullable String[] getDependsOn(); void setAutowireCandidate (boolean autowireCandidate) ; boolean isAutowireCandidate () ; void setPrimary (boolean primary) ; boolean isPrimary () ; void setFactoryBeanName (@Nullable String factoryBeanName) ; @Nullable String getFactoryBeanName () ; void setFactoryMethodName (@Nullable String factoryMethodName) ; @Nullable String getFactoryMethodName () ; ConstructorArgumentValues getConstructorArgumentValues () ; default boolean hasConstructorArgumentValues () { return !getConstructorArgumentValues().isEmpty(); } MutablePropertyValues getPropertyValues () ; default boolean hasPropertyValues () { return !getPropertyValues().isEmpty(); } boolean isSingleton () ; boolean isPrototype () ; boolean isAbstract () ; int getRole () ; @Nullable String getDescription () ; @Nullable String getResourceDescription () ; @Nullable BeanDefinition getOriginatingBeanDefinition () ; }
父类 BeanDefinition
继承 AttributeAccessor
和 BeanMetadataElement
接口。两个接口定义如下:
子类 BeanDefinition
整个结构如下图:
我们常用的三个实现类有:ChildBeanDefinition
、GenericBeanDefinition
、RootBeanDefinition
,三者都继承 AbstractBeanDefinition
。如果配置文件中定义了父
和 子
,则父 用 RootBeanDefinition
表示,子 用 ChildBeanDefinition
表示,而没有父的就使用RootBeanDefinition
表示。GenericBeanDefinition
为一站式服务类。AbstractBeanDefinition
对三个子类共同的类信息进行抽象。
解析 Bean 标签 在 BeanDefinitionParserDelegate.parseBeanDefinitionElement()
中完成 Bean
的解析,返回的是一个已经完成对 标签解析的 BeanDefinition
实例。
createBeanDefinition 在该方法内部,首先调用 createBeanDefinition()
方法创建一个用于承载属性的 GenericBeanDefinition
实例,如下:
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
。
parseBeanDefinitionAttributes 创建完 GenericBeanDefinition
实例后,再调用 parseBeanDefinitionAttributes()
,该方法将创建好的 GenericBeanDefinition
实例当做参数,对 Bean
标签的所有属性进行解析,如下:
public AbstractBeanDefinition parseBeanDefinitionAttributes ( Element ele, String beanName, @Nullable 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 ) { 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)); 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); 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; }
从上面代码我们可以清晰地看到对 Bean
标签属性的解析,这些属性我们在工作中都或多或少用到过。 完成 Bean 标签基本属性解析后,会依次调用 parseMetaElements()
、parseLookupOverrideSubElements()
、parseReplacedMethodSubElements()
对子元素 meta
、lookup-method
、replace-method
完成解析。下篇博文将会对这三个子元素进行详细说明。