spring IOC 之篇三:默认标签的解析
這里主要分新bean標簽的處理,其他都類似
?
/*** Process the given bean element, parsing the bean definition* and registering it with the registry.*/protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) { // 首先委托 BeanDefinitionParserDelegate 類的parseBeanDefinitionElement方法進行元素的解析,返回實例BeanDefinitionHolder 對象,經過這個方法后,bdHolder實例已經包含我們配置的配置文件中的各種屬性了,列如:class,id,alias之類的屬性了。BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);if (bdHolder != null) { // 當返回的BeanDefinitionHolder對象實例 bdHolder不為空的情況下若存在默認標簽的字節點下再有自定義屬性,還需要再次對自定義屬性進行解析。bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);try {// Register the final decorated instance. //解析完成后,需要對解析后的bdHolder進行注冊,同樣,注冊操作委托給了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. //最后發出響應事件,通知相關的監聽器,這個bean已經加載完成了。getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));}}?
繼續深入分析 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);}// 進一步解析bean的其他屬性 并封裝到對象 GenericBeanDefinition對象中AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);if (beanDefinition != null) {if (!StringUtils.hasText(beanName)) {try {if (containingBean != null) {// 如果不存在 beanName,則使用Spring提供的命名規則默認生成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 實例中去 return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray); } return null; }
?
接下來進一步分析對其他bean標簽的解析方法:
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);}// 創建用于承載bean各種標簽的 GenericBeanDefinition對象AbstractBeanDefinition bd = createBeanDefinition(className, parent);// 硬編碼解析bean的屬性 例如:singleton、destroy-method等 parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);// 提取 desciption bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));// 解析元數據 parseMetaElements(ele, bd);// 解析lookup-method屬性 parseLookupOverrideSubElements(ele, bd.getMethodOverrides());// 解析repalce-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;}進一步分析創建屬性承載的BeanDefinition對象
BeanDefinition是一個接口,spring中三種實現形式:RootBeanDefinition、ChildBeanDefinition和GenericBeanDefinition。三種實現類均繼承了AbstractBeanDefinition,其中BeanDefinition是<bean>標簽在容器內部的表現形式,BeanDefinition和<bean>的屬性是一一對應的。Spring通過BeanDefinition將配置文件中的信息裝換為內部的表現形式,并將這些BeanDefinition注冊到BeanDefinitionRegistry中。
?至此 已經完成XML文檔像GenericBeandefinition的全部裝換。GenericBeandefinition只是子類實現,大部分屬性封裝在AbstractBeandefinition對象中,我們繼續分析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的作用范圍,對應bean的屬性 scopeprivate String scope = SCOPE_DEFAULT;// 是否抽象標識,默認false,對應bean的屬性 abstractprivate boolean abstractFlag = false;// 是否延遲加載,對應bean的屬性 lazy-initprivate boolean lazyInit = false;// 是否自動注入模式,對應bean的屬性autowireprivate int autowireMode = AUTOWIRE_NO; // 依賴檢查,spring3以后棄用這個屬性private int dependencyCheck = DEPENDENCY_CHECK_NONE; // 用來表示一個bean的實例化,依賴另一個bean實例化,對應bean的屬性depend-onprivate String[] dependsOn; // autowire-candidate屬性設置為false,這樣容器在查找自動裝配對象的時候,將不會考慮該bean,即不會考慮該bean作為其他bean的自動裝配候選者private boolean autowireCandidate = true; // 當自動裝配出現多個bean,如果primary為true,則改bean作為首席候選者private boolean primary = false; // 用于記錄 Qualifier 對應子元素 qualifierprivate final Map<String, AutowireCandidateQualifier> qualifiers =new LinkedHashMap<String, AutowireCandidateQualifier>(0);private boolean nonPublicAccessAllowed = true;private boolean lenientConstructorResolution = true;//記錄構造函數注入屬性,對應屬性值 constructor-argprivate ConstructorArgumentValues ArgumentValues; // 普通屬性集合private MutablePropertyValues propertyValues; // 記錄 lookup-method和replace-method屬性值private MethodOverrides methodOverrides = new MethodOverrides();private String factoryBeanName;private String factoryMethodName; // 初始化方法 對應屬性 init-methodprivate String initMethodName; // 銷毀方法 對應屬性 destroy-method private String destroyMethodName; // 是否執行 init-method 程序設置private boolean enforceInitMethod = true; // 是否執行 destroy-method 程序設置private boolean enforceDestroyMethod = true;// 使用用戶自定義而不是應用程序本身定義的,創建AOP時候為trueprivate boolean synthetic = false;private int role = BeanDefinition.ROLE_APPLICATION;private String description; // 這個bean定義的資源private Resource resource;?
解析完成以后,會將所有的xml屬性值封裝至對象 GenericBeanDefinition中,然后會進行注冊。
針對以下代碼進行分析:
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry())
// 解析完以后,BeanDefinition對象就注冊到了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作為唯一注冊標識String beanName = definitionHolder.getBeanName();registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());// Register aliases for bean name, if any.// 注冊所有的bean的別名String[] aliases = definitionHolder.getAliases();if (aliases != null) {for (String alias : aliases) {registry.registerAlias(beanName, alias);}}}?
繼續深入解析:
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 {// 注冊前的最后一次校驗,這里主要校驗AbstractBeandefinition 中的methodOverrides 屬性,校驗methodOverrides是否與工廠方法共存,或者對應的方法根本不存在 ((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) {// 對于已經注冊過的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) //因為 beanDefinitionMap 是全局變量,這里會存在并發的情況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// 注冊beanDefinitionthis.beanDefinitionMap.put(beanName, beanDefinition);// 記錄所有的beanNamesthis.beanDefinitionNames.add(beanName);this.manualSingletonNames.remove(beanName);}this.frozenBeanDefinitionNames = null;}if (oldBeanDefinition != null || containsSingleton(beanName)) {// 重置beanName所有的對應的緩存 resetBeanDefinition(beanName);}}注冊完成,通知所有的監聽事件:
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
這里是spring留給子類進行擴展的。
?
轉載于:https://www.cnblogs.com/histlyb/p/8977554.html
總結
以上是生活随笔為你收集整理的spring IOC 之篇三:默认标签的解析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 学习Java 采取令牌的方式避免重复提交
- 下一篇: loj #2305. 「NOI2017」