死磕Spring之IoC篇 - 解析自定义标签(XML 文件) (3)

注意有一个 DEFAULT_HANDLER_MAPPINGS_LOCATION 属性为 META-INF/spring.handlers,我们定义的 spring.handlers 在这里出现了,说明命名空间和对应的处理器在这里大概率会有体现

还有一个 handlerMappingsLocation 属性默认为 META-INF/spring.handlers

resolve 方法

resolve(String namespaceUri) 方法,根据命名空间找到对应的 NamespaceHandler 处理器,方法如下:

@Override @Nullable public NamespaceHandler resolve(String namespaceUri) { // <1> 获取所有已经配置的命名空间与 NamespaceHandler 处理器的映射 Map<String, Object> handlerMappings = getHandlerMappings(); // <2> 根据 `namespaceUri` 命名空间获取 NamespaceHandler 处理器 Object handlerOrClassName = handlerMappings.get(namespaceUri); // <3> 接下来对 NamespaceHandler 进行初始化,因为定义在 `spring.handler` 文件中,可能还没有转换成 Class 类对象 // <3.1> 不存在 if (handlerOrClassName == null) { return null; } // <3.2> 已经初始化 else if (handlerOrClassName instanceof NamespaceHandler) { return (NamespaceHandler) handlerOrClassName; } // <3.3> 需要进行初始化 else { String className = (String) handlerOrClassName; try { // 获得类,并创建 NamespaceHandler 对象 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"); } NamespaceHandler namespaceHandler = (NamespaceHandler) BeanUtils.instantiateClass(handlerClass); // 初始化 NamespaceHandler 对象 namespaceHandler.init(); // 添加到缓存 handlerMappings.put(namespaceUri, namespaceHandler); return namespaceHandler; } catch (ClassNotFoundException ex) { throw new FatalBeanException("Could not find NamespaceHandler class [" + className + "] for namespace [" + namespaceUri + "]", ex); } catch (LinkageError err) { throw new FatalBeanException("Unresolvable class definition for NamespaceHandler class [" + className + "] for namespace [" + namespaceUri + "]", err); } } }

过程如下:

获取所有已经配置的命名空间与 NamespaceHandler 处理器的映射,调用 getHandlerMappings() 方法

根据 namespaceUri 命名空间获取 NamespaceHandler 处理器

接下来对 NamespaceHandler 进行初始化,因为定义在 spring.handler 文件中,可能还没有转换成 Class 类对象

不存在则返回空对象

否则,已经初始化则直接返回

否则,根据 className 创建一个 Class 对象,然后进行实例化,还调用其 init() 方法

该方法可以找到命名空间对应的 NamespaceHandler 处理器,关键在于第 1 步如何将 spring.handlers 文件中的内容返回的

getHandlerMappings 方法

getHandlerMappings() 方法,从所有的 META-INF/spring.handlers 文件中获取命名空间与处理器之间的映射,方法如下:

private Map<String, Object> getHandlerMappings() { // 双重检查锁,延迟加载 Map<String, Object> handlerMappings = this.handlerMappings; if (handlerMappings == null) { synchronized (this) { handlerMappings = this.handlerMappings; if (handlerMappings == null) { if (logger.isTraceEnabled()) { logger.trace("Loading NamespaceHandler mappings from [" + this.handlerMappingsLocation + "]"); } try { // 读取 `handlerMappingsLocation`,也就是当前 JVM 环境下所有的 `META-INF/spring.handlers` 文件的内容都会读取到 Properties mappings = PropertiesLoaderUtils.loadAllProperties(this.handlerMappingsLocation, this.classLoader); if (logger.isTraceEnabled()) { logger.trace("Loaded NamespaceHandler mappings: " + mappings); } // 初始化到 `handlerMappings` 中 handlerMappings = new ConcurrentHashMap<>(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 handlerMappings; }

逻辑不复杂,会读取当前 JVM 环境下所有的 META-INF/spring.handlers 文件,将里面的内容以 key-value 的形式保存在 Map 中返回

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zwdfxz.html