您好,登錄后才能下訂單哦!
這篇“Spring是如何擴展解析xml接口的”文章的知識點大部分人都不太理解,所以小編給大家總結了以下內容,內容詳細,步驟清晰,具有一定的借鑒價值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“Spring是如何擴展解析xml接口的”文章吧。
Java自定義Spring配置標簽
在DefaultBeanDefinitionDocumentReader處理Document元素時,將Document文檔內元素具體解析工作委托給BeanDefinitionParserDelegate類來處理,默認BeanDefinitionParserDelegate會處理”
public class BeanDefinitionParserDelegate { public static final String BEANS_NAMESPACE_URI = "http://www.springframework.org/schema/beans"; public static final String MULTI_VALUE_ATTRIBUTE_DELIMITERS = ",; "; private final XmlReaderContext readerContext; private final DocumentDefaultsDefinition defaults = new DocumentDefaultsDefinition(); /** *初始化 default lazy-init, autowire, dependency check settings, * init-method, destroy-method and merge settings等屬性值 * 并且填充到屬性 DocumentDefaultsDefinition defaults; * 如果 當前Xml文件沒有配置默認屬性,則查父類delegate有沒有設置屬性;如果沒有則 使用默認配置 */ protected void populateDefaults(DocumentDefaultsDefinition defaults, DocumentDefaultsDefinition parentDefaults, Element root) { String lazyInit = root.getAttribute(DEFAULT_LAZY_INIT_ATTRIBUTE); if (DEFAULT_VALUE.equals(lazyInit)) { // Potentially inherited from outer <beans> sections, otherwise falling back to false. lazyInit = (parentDefaults != null ? parentDefaults.getLazyInit() : FALSE_VALUE); } defaults.setLazyInit(lazyInit); String merge = root.getAttribute(DEFAULT_MERGE_ATTRIBUTE); if (DEFAULT_VALUE.equals(merge)) { // Potentially inherited from outer <beans> sections, otherwise falling back to false. merge = (parentDefaults != null ? parentDefaults.getMerge() : FALSE_VALUE); } defaults.setMerge(merge); String autowire = root.getAttribute(DEFAULT_AUTOWIRE_ATTRIBUTE); if (DEFAULT_VALUE.equals(autowire)) { // Potentially inherited from outer <beans> sections, otherwise falling back to 'no'. autowire = (parentDefaults != null ? parentDefaults.getAutowire() : AUTOWIRE_NO_VALUE); } defaults.setAutowire(autowire); // Don't fall back to parentDefaults for dependency-check as it's no longer supported in // <beans> as of 3.0. Therefore, no nested <beans> would ever need to fall back to it. defaults.setDependencyCheck(root.getAttribute(DEFAULT_DEPENDENCY_CHECK_ATTRIBUTE)); if (root.hasAttribute(DEFAULT_AUTOWIRE_CANDIDATES_ATTRIBUTE)) { defaults.setAutowireCandidates(root.getAttribute(DEFAULT_AUTOWIRE_CANDIDATES_ATTRIBUTE)); } else if (parentDefaults != null) { defaults.setAutowireCandidates(parentDefaults.getAutowireCandidates()); } if (root.hasAttribute(DEFAULT_INIT_METHOD_ATTRIBUTE)) { defaults.setInitMethod(root.getAttribute(DEFAULT_INIT_METHOD_ATTRIBUTE)); } else if (parentDefaults != null) { defaults.setInitMethod(parentDefaults.getInitMethod()); } if (root.hasAttribute(DEFAULT_DESTROY_METHOD_ATTRIBUTE)) { defaults.setDestroyMethod(root.getAttribute(DEFAULT_DESTROY_METHOD_ATTRIBUTE)); } else if (parentDefaults != null) { defaults.setDestroyMethod(parentDefaults.getDestroyMethod()); } defaults.setSource(this.readerContext.extractSource(root)); } //解析自定義元素 public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) { //獲取當前Element的命名空間 String namespaceUri = getNamespaceURI(ele); //獲取namespaceHandlerResolver然后根據命名空間得到具體的 NamespaceHandler處理類 NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri); if (handler == null) { error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele); return null; } //具體的NamespaceHandler處理類去解析Element;返回 BeanDefinition 對象 return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd)); } //返回defaults屬性值 public BeanDefinitionDefaults getBeanDefinitionDefaults() { BeanDefinitionDefaults bdd = new BeanDefinitionDefaults(); bdd.setLazyInit("TRUE".equalsIgnoreCase(this.defaults.getLazyInit())); bdd.setDependencyCheck(this.getDependencyCheck(DEFAULT_VALUE)); bdd.setAutowireMode(this.getAutowireMode(DEFAULT_VALUE)); bdd.setInitMethodName(this.defaults.getInitMethod()); bdd.setDestroyMethodName(this.defaults.getDestroyMethod()); return bdd; }
DefaultNamespaceHandlerResolver implements NamespaceHandlerResolver; 默認的 命名空間解析對象選擇器; 主要作用就是 根據不同的命名空間來選擇對應的解析器;
/** * Locate the {@link NamespaceHandler} for the supplied namespace URI * from the configured mappings. * @param namespaceUri the relevant namespace URI * @return the located {@link NamespaceHandler}, or {@code null} if none found */ @Override public NamespaceHandler resolve(String namespaceUri) { Map<String, Object> handlerMappings = getHandlerMappings(); Object handlerOrClassName = handlerMappings.get(namespaceUri); if (handlerOrClassName == null) { return null; } //如果已經把全類名路徑轉換成具體的實例了 就直接返回 else if (handlerOrClassName instanceof NamespaceHandler) { return (NamespaceHandler) handlerOrClassName; } else { String className = (String) handlerOrClassName; try { //根據全類名路徑 來加載這個類 Class<?> handlerClass = ClassUtils.forName(className, this.classLoader); if (!NamespaceHandler.class.isAssignableFrom(handlerClass)) { throw new FatalBeanException("Class [" + className + "] for namespace [" + namespaceUri + "] does not implement the [" + NamespaceHandler.class.getName() + "] interface"); } //加載完類之后,通過反射生成具體實例對象;例如:ContextNamespaceHandler NamespaceHandler namespaceHandler = (NamespaceHandler) BeanUtils.instantiateClass(handlerClass); //調用具體對象的init()方法,注冊對應的解析類,例如annotation-config 對應的解析類是 AnnotationConfigBeanDefinitionParser namespaceHandler.init(); //將實例對象覆蓋 全類名路徑 handlerMappings.put(namespaceUri, namespaceHandler); return namespaceHandler; } catch (ClassNotFoundException ex) { throw new FatalBeanException("NamespaceHandler class [" + className + "] for namespace [" + namespaceUri + "] not found", ex); } catch (LinkageError err) { throw new FatalBeanException("Invalid NamespaceHandler class [" + className + "] for namespace [" + namespaceUri + "]: problem with handler class file or dependent class", err); } } } /** * 第一次加載的時候 Map里面的對象 是String類型,全類名路徑 */ private Map<String, Object> getHandlerMappings() { if (this.handlerMappings == null) { synchronized (this) { if (this.handlerMappings == null) { //加載META-INF/spring.handlers的所有屬性 Properties mappings = PropertiesLoaderUtils.loadAllProperties(this.handlerMappingsLocation, this.classLoader); if (logger.isDebugEnabled()) { logger.debug("Loaded NamespaceHandler mappings: " + mappings); } Map<String, Object> handlerMappings = new ConcurrentHashMap<String, Object>(mappings.size()); CollectionUtils.mergePropertiesIntoMap(mappings, handlerMappings); this.handlerMappings = handlerMappings; } catch (IOException ex) { throw new IllegalStateException( "Unable to load NamespaceHandler mappings from location [" + this.handlerMappingsLocation + "]", ex); } } } } return this.handlerMappings; }
實現了NamespaceHandler中的parse()和decorate方法,并且提供一些屬性來維護 具體的解析元素的對象BeanDefinitionParser; 例如:www.springframework.org/schema/cont… 命名空間對應的操作類是 ContextNamespaceHandler; 這個操作類會調用init()方法
@Override public void init() { registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser()); registerBeanDefinitionParser("property-override", new PropertyOverrideBeanDefinitionParser()); registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser()); registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser()); registerBeanDefinitionParser("load-time-weaver", new LoadTimeWeaverBeanDefinitionParser()); registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser()); registerBeanDefinitionParser("mbean-export", new MBeanExportBeanDefinitionParser()); registerBeanDefinitionParser("mbean-server", new MBeanServerBeanDefinitionParser()); }
根據不同的屬性,注冊不同的解析類 BeanDefinitionParser
我們以ContextNamespaceHandler看下, 實現類只要實現init方法就行了; 對應的解析類 通過registerBeanDefinitionParser方法,存放到NamespaceHandlerSupport中的Map parsers 中
public abstract class NamespaceHandlerSupport implements NamespaceHandler { //將元素頭 與對應的解析器對應起來 protected final void registerBeanDefinitionParser(String elementName, BeanDefinitionParser parser) { this.parsers.put(elementName, parser); } /** *具體的NamespaceHandler處理類去解析Element;返回 BeanDefinition 對象 * BeanDefinitionParserDelegate.parseCustomElement 中 在獲取到了對應的handler后,會執行handler.parse(ele, new ParserContext(this.readerContext, this, containingBd))方法; * 例如:獲取到的操作類是 ContextNamespaceHandler,調用parse的方法其實調用了NamespaceHandlerSupportde parse方法;也就是下面的 * 例如annotation-config得到的是AnnotationConfigBeanDefinitionParser實例, 再調用AnnotationConfigBeanDefinitionParser的parse方法;這樣就實現了根據不同元素來解析成 Spring中的 定義Bean BeanDefinition了; */ @Override public BeanDefinition parse(Element element, ParserContext parserContext) { return findParserForElement(element, parserContext).parse(element, parserContext); } /** * 根據元素節點的名稱 獲取對應的解析類實例;例如annotation-config得到的是AnnotationConfigBeanDefinitionParser實例, */ private BeanDefinitionParser findParserForElement(Element element, ParserContext parserContext) { String localName = parserContext.getDelegate().getLocalName(element); BeanDefinitionParser parser = this.parsers.get(localName); if (parser == null) { parserContext.getReaderContext().fatal( "Cannot locate BeanDefinitionParser for element [" + localName + "]", element); } return parser; } }
public class ContextNamespaceHandler extends NamespaceHandlerSupport { @Override public void init() { registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser()); registerBeanDefinitionParser("property-override", new PropertyOverrideBeanDefinitionParser()); registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser()); registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser()); registerBeanDefinitionParser("load-time-weaver", new LoadTimeWeaverBeanDefinitionParser()); registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser()); registerBeanDefinitionParser("mbean-export", new MBeanExportBeanDefinitionParser()); registerBeanDefinitionParser("mbean-server", new MBeanServerBeanDefinitionParser()); } }
Element元素的解析類;只有一個方法BeanDefinition parse(Element element, ParserContext parserContext); 實現類去實現這個方法就行了;
我們看到parse方法中傳入了ParserContext 參數;我們了解一下這個;
解析類上下文;這類hold住了 XmlReaderContext和 BeanDefinitionParserDelegate;可以最大限度的讓用戶自已去解析
public ParserContext(XmlReaderContext readerContext, BeanDefinitionParserDelegate delegate, BeanDefinition containingBeanDefinition) { this.readerContext = readerContext; this.delegate = delegate; this.containingBeanDefinition = containingBeanDefinition; }
以上就是關于“Spring是如何擴展解析xml接口的”這篇文章的內容,相信大家都有了一定的了解,希望小編分享的內容對大家有幫助,若想了解更多相關的知識內容,請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。