spring IOC 之篇三:默认标签的解析
這里主要分新bean標(biāo)簽的處理,其他都類似
?
/*** Process the given bean element, parsing the bean definition* and registering it with the registry.*/protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) { // 首先委托 BeanDefinitionParserDelegate 類的parseBeanDefinitionElement方法進(jìn)行元素的解析,返回實(shí)例BeanDefinitionHolder 對(duì)象,經(jīng)過(guò)這個(gè)方法后,bdHolder實(shí)例已經(jīng)包含我們配置的配置文件中的各種屬性了,列如:class,id,alias之類的屬性了。BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);if (bdHolder != null) { // 當(dāng)返回的BeanDefinitionHolder對(duì)象實(shí)例 bdHolder不為空的情況下若存在默認(rèn)標(biāo)簽的字節(jié)點(diǎn)下再有自定義屬性,還需要再次對(duì)自定義屬性進(jìn)行解析。bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);try {// Register the final decorated instance. //解析完成后,需要對(duì)解析后的bdHolder進(jìn)行注冊(cè),同樣,注冊(cè)操作委托給了BeanDefinitionReaderUtils的registerBeanDefinition方法。 BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());}catch (BeanDefinitionStoreException ex) {getReaderContext().error("Failed to register bean definition with name '" +bdHolder.getBeanName() + "'", ele, ex);}// Send registration event. //最后發(fā)出響應(yīng)事件,通知相關(guān)的監(jiān)聽(tīng)器,這個(gè)bean已經(jīng)加載完成了。getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));}}?
繼續(xù)深入分析 BeanDefinitionParserDelegate 類的parseBeanDefinitionElement方法:
?
/*** Parses the supplied {@code <bean>} element. May return {@code null}* if there were errors during parse. Errors are reported to the* {@link org.springframework.beans.factory.parsing.ProblemReporter}.*/public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {// 解析id屬性String id = ele.getAttribute(ID_ATTRIBUTE);// 解析name屬性String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);// 分隔name屬性 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()) {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);}// 進(jìn)一步解析bean的其他屬性 并封裝到對(duì)象 GenericBeanDefinition對(duì)象中AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);if (beanDefinition != null) {if (!StringUtils.hasText(beanName)) {try {if (containingBean != null) {// 如果不存在 beanName,則使用Spring提供的命名規(guī)則默認(rèn)生成beanNamebeanName = BeanDefinitionReaderUtils.generateBeanName(beanDefinition, this.readerContext.getRegistry(), true);}else {// 如果有則獲取beanNamebeanName = 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 實(shí)例中去 return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray); } return null; }
?
接下來(lái)進(jìn)一步分析對(duì)其他bean標(biāo)簽的解析方法:
AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
/*** Parse the bean definition itself, without regard to name or aliases. May return* {@code null} if problems occurred during the parsing of the bean definition.*/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);}// 創(chuàng)建用于承載bean各種標(biāo)簽的 GenericBeanDefinition對(duì)象AbstractBeanDefinition bd = createBeanDefinition(className, parent);// 硬編碼解析bean的屬性 例如:singleton、destroy-method等 parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);// 提取 desciption bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));// 解析元數(shù)據(jù) parseMetaElements(ele, bd);// 解析lookup-method屬性 parseLookupOverrideSubElements(ele, bd.getMethodOverrides());// 解析repalce-method屬性 parseReplacedMethodSubElements(ele, bd.getMethodOverrides());// 解析構(gòu)造函數(shù)參數(shù) 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;}進(jìn)一步分析創(chuàng)建屬性承載的BeanDefinition對(duì)象
BeanDefinition是一個(gè)接口,spring中三種實(shí)現(xiàn)形式:RootBeanDefinition、ChildBeanDefinition和GenericBeanDefinition。三種實(shí)現(xiàn)類均繼承了AbstractBeanDefinition,其中BeanDefinition是<bean>標(biāo)簽在容器內(nèi)部的表現(xiàn)形式,BeanDefinition和<bean>的屬性是一一對(duì)應(yīng)的。Spring通過(guò)BeanDefinition將配置文件中的信息裝換為內(nèi)部的表現(xiàn)形式,并將這些BeanDefinition注冊(cè)到BeanDefinitionRegistry中。
?至此 已經(jīng)完成XML文檔像GenericBeandefinition的全部裝換。GenericBeandefinition只是子類實(shí)現(xiàn),大部分屬性封裝在AbstractBeandefinition對(duì)象中,我們繼續(xù)分析AbstractBeandefinition的給中屬性:
@SuppressWarnings("serial") public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccessorimplements BeanDefinition, Cloneable {/*** Constant for the default scope name: {@code ""}, equivalent to singleton* status unless overridden from a parent bean definition (if applicable).*/public static final String SCOPE_DEFAULT = "";/*** Constant that indicates no autowiring at all.* @see #setAutowireMode*/public static final int AUTOWIRE_NO = AutowireCapableBeanFactory.AUTOWIRE_NO;/*** Constant that indicates autowiring bean properties by name.* @see #setAutowireMode*/public static final int AUTOWIRE_BY_NAME = AutowireCapableBeanFactory.AUTOWIRE_BY_NAME;/*** Constant that indicates autowiring bean properties by type.* @see #setAutowireMode*/public static final int AUTOWIRE_BY_TYPE = AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE;/*** Constant that indicates autowiring a constructor.* @see #setAutowireMode*/public static final int AUTOWIRE_CONSTRUCTOR = AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR;/*** Constant that indicates determining an appropriate autowire strategy* through introspection of the bean class.* @see #setAutowireMode* @deprecated as of Spring 3.0: If you are using mixed autowiring strategies,* use annotation-based autowiring for clearer demarcation of autowiring needs.*/@Deprecatedpublic static final int AUTOWIRE_AUTODETECT = AutowireCapableBeanFactory.AUTOWIRE_AUTODETECT;/*** Constant that indicates no dependency check at all.* @see #setDependencyCheck*/public static final int DEPENDENCY_CHECK_NONE = 0;/*** Constant that indicates dependency checking for object references.* @see #setDependencyCheck*/public static final int DEPENDENCY_CHECK_OBJECTS = 1;/*** Constant that indicates dependency checking for "simple" properties.* @see #setDependencyCheck* @see org.springframework.beans.BeanUtils#isSimpleProperty*/public static final int DEPENDENCY_CHECK_SIMPLE = 2;/*** Constant that indicates dependency checking for all properties* (object references as well as "simple" properties).* @see #setDependencyCheck*/public static final int DEPENDENCY_CHECK_ALL = 3;/*** Constant that indicates the container should attempt to infer the* {@link #setDestroyMethodName destroy method name} for a bean as opposed to* explicit specification of a method name. The value {@value} is specifically* designed to include characters otherwise illegal in a method name, ensuring* no possibility of collisions with legitimately named methods having the same* name.* <p>Currently, the method names detected during destroy method inference* are "close" and "shutdown", if present on the specific bean class.*/public static final String INFER_METHOD = "(inferred)";private volatile Object beanClass;// bean的作用范圍,對(duì)應(yīng)bean的屬性 scopeprivate String scope = SCOPE_DEFAULT;// 是否抽象標(biāo)識(shí),默認(rèn)false,對(duì)應(yīng)bean的屬性 abstractprivate boolean abstractFlag = false;// 是否延遲加載,對(duì)應(yīng)bean的屬性 lazy-initprivate boolean lazyInit = false;// 是否自動(dòng)注入模式,對(duì)應(yīng)bean的屬性autowireprivate int autowireMode = AUTOWIRE_NO; // 依賴檢查,spring3以后棄用這個(gè)屬性private int dependencyCheck = DEPENDENCY_CHECK_NONE; // 用來(lái)表示一個(gè)bean的實(shí)例化,依賴另一個(gè)bean實(shí)例化,對(duì)應(yīng)bean的屬性depend-onprivate String[] dependsOn; // autowire-candidate屬性設(shè)置為false,這樣容器在查找自動(dòng)裝配對(duì)象的時(shí)候,將不會(huì)考慮該bean,即不會(huì)考慮該bean作為其他bean的自動(dòng)裝配候選者private boolean autowireCandidate = true; // 當(dāng)自動(dòng)裝配出現(xiàn)多個(gè)bean,如果primary為true,則改bean作為首席候選者private boolean primary = false; // 用于記錄 Qualifier 對(duì)應(yīng)子元素 qualifierprivate final Map<String, AutowireCandidateQualifier> qualifiers =new LinkedHashMap<String, AutowireCandidateQualifier>(0);private boolean nonPublicAccessAllowed = true;private boolean lenientConstructorResolution = true;//記錄構(gòu)造函數(shù)注入屬性,對(duì)應(yīng)屬性值 constructor-argprivate ConstructorArgumentValues ArgumentValues; // 普通屬性集合private MutablePropertyValues propertyValues; // 記錄 lookup-method和replace-method屬性值private MethodOverrides methodOverrides = new MethodOverrides();private String factoryBeanName;private String factoryMethodName; // 初始化方法 對(duì)應(yīng)屬性 init-methodprivate String initMethodName; // 銷毀方法 對(duì)應(yīng)屬性 destroy-method private String destroyMethodName; // 是否執(zhí)行 init-method 程序設(shè)置private boolean enforceInitMethod = true; // 是否執(zhí)行 destroy-method 程序設(shè)置private boolean enforceDestroyMethod = true;// 使用用戶自定義而不是應(yīng)用程序本身定義的,創(chuàng)建AOP時(shí)候?yàn)閠rueprivate boolean synthetic = false;private int role = BeanDefinition.ROLE_APPLICATION;private String description; // 這個(gè)bean定義的資源private Resource resource;?
解析完成以后,會(huì)將所有的xml屬性值封裝至對(duì)象 GenericBeanDefinition中,然后會(huì)進(jìn)行注冊(cè)。
針對(duì)以下代碼進(jìn)行分析:
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry())
// 解析完以后,BeanDefinition對(duì)象就注冊(cè)到了BeanDefinitionRegisty集合中去了。將beanName作為Key,BeanDefinition作為value。
?
/*** Register the given bean definition with the given bean factory.* @param definitionHolder the bean definition including name and aliases* @param registry the bean factory to register with* @throws BeanDefinitionStoreException if registration failed*/public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)throws BeanDefinitionStoreException {// Register bean definition under primary name.// 使用beanName作為唯一注冊(cè)標(biāo)識(shí)String beanName = definitionHolder.getBeanName();registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());// Register aliases for bean name, if any.// 注冊(cè)所有的bean的別名String[] aliases = definitionHolder.getAliases();if (aliases != null) {for (String alias : aliases) {registry.registerAlias(beanName, alias);}}}?
繼續(xù)深入解析:
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
@Overridepublic void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)throws BeanDefinitionStoreException {Assert.hasText(beanName, "Bean name must not be empty");Assert.notNull(beanDefinition, "BeanDefinition must not be null");if (beanDefinition instanceof AbstractBeanDefinition) {try {// 注冊(cè)前的最后一次校驗(yàn),這里主要校驗(yàn)AbstractBeandefinition 中的methodOverrides 屬性,校驗(yàn)methodOverrides是否與工廠方法共存,或者對(duì)應(yīng)的方法根本不存在 ((AbstractBeanDefinition) beanDefinition).validate();}catch (BeanDefinitionValidationException ex) {throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,"Validation of bean definition failed", ex);}}BeanDefinition oldBeanDefinition;oldBeanDefinition = this.beanDefinitionMap.get(beanName);if (oldBeanDefinition != null) {// 對(duì)于已經(jīng)注冊(cè)過(guò)的bean,如果不允許覆蓋,則直接拋出異常if (!isAllowBeanDefinitionOverriding()) {throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,"Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +"': There is already [" + oldBeanDefinition + "] bound.");}else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTUREif (this.logger.isWarnEnabled()) {this.logger.warn("Overriding user-defined bean definition for bean '" + beanName +"' with a framework-generated bean definition: replacing [" +oldBeanDefinition + "] with [" + beanDefinition + "]");}}else if (!beanDefinition.equals(oldBeanDefinition)) {if (this.logger.isInfoEnabled()) {this.logger.info("Overriding bean definition for bean '" + beanName +"' with a different definition: replacing [" + oldBeanDefinition +"] with [" + beanDefinition + "]");}}else {if (this.logger.isDebugEnabled()) {this.logger.debug("Overriding bean definition for bean '" + beanName +"' with an equivalent definition: replacing [" + oldBeanDefinition +"] with [" + beanDefinition + "]");}}this.beanDefinitionMap.put(beanName, beanDefinition);}else {if (hasBeanCreationStarted()) {// Cannot modify startup-time collection elements anymore (for stable iteration) //因?yàn)?beanDefinitionMap 是全局變量,這里會(huì)存在并發(fā)的情況synchronized (this.beanDefinitionMap) {this.beanDefinitionMap.put(beanName, beanDefinition);List<String> updatedDefinitions = new ArrayList<String>(this.beanDefinitionNames.size() + 1);updatedDefinitions.addAll(this.beanDefinitionNames);updatedDefinitions.add(beanName);this.beanDefinitionNames = updatedDefinitions;if (this.manualSingletonNames.contains(beanName)) {Set<String> updatedSingletons = new LinkedHashSet<String>(this.manualSingletonNames);updatedSingletons.remove(beanName);this.manualSingletonNames = updatedSingletons;}}}else {// Still in startup registration phase// 注冊(cè)beanDefinitionthis.beanDefinitionMap.put(beanName, beanDefinition);// 記錄所有的beanNamesthis.beanDefinitionNames.add(beanName);this.manualSingletonNames.remove(beanName);}this.frozenBeanDefinitionNames = null;}if (oldBeanDefinition != null || containsSingleton(beanName)) {// 重置beanName所有的對(duì)應(yīng)的緩存 resetBeanDefinition(beanName);}}注冊(cè)完成,通知所有的監(jiān)聽(tīng)事件:
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
這里是spring留給子類進(jìn)行擴(kuò)展的。
?
轉(zhuǎn)載于:https://www.cnblogs.com/histlyb/p/8977554.html
總結(jié)
以上是生活随笔為你收集整理的spring IOC 之篇三:默认标签的解析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 学习Java 采取令牌的方式避免重复提交
- 下一篇: loj #2305. 「NOI2017」