当前位置: 首页 > news >正文

沙井网站制作网站怎么做rss订阅功能

沙井网站制作,网站怎么做rss订阅功能,我想学网站建设,网站怎么找回密码我们知道#xff0c;在 spring 的配置文件解析时#xff0c;通过 XmlBeanDefinitionReader 来操作#xff0c;下面来看看对 XML 配置文件解析时#xff0c;这个类具体是如何操作的。 入口 protected int doLoadBeanDefinitions(InputSource inputSource, Resource resour…我们知道在 spring 的配置文件解析时通过 XmlBeanDefinitionReader 来操作下面来看看对 XML 配置文件解析时这个类具体是如何操作的。 入口 protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)throws BeanDefinitionStoreException {Document doc doLoadDocument(inputSource, resource);int count registerBeanDefinitions(doc, resource);return count; } 核心逻辑就两行 第一行将 xml 转换为 org.w3c.dom.Document方便后续 registerBeanDefinitions 操作转换使用 JAXP 中的 DOM 解析来操作。 第二行从名字可以看出注册所有 BeanDefinition这也是接下来的重点。 registerBeanDefinitions 要注册 BeanDefinition就需要先解析出 BeanDefinition。 public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {BeanDefinitionDocumentReader documentReader createBeanDefinitionDocumentReader();int countBefore getRegistry().getBeanDefinitionCount();documentReader.registerBeanDefinitions(doc, createReaderContext(resource));return getRegistry().getBeanDefinitionCount() - countBefore; } 先创建一个 BeanDefinitionDocumentReader此处为 DefaultBeanDefinitionDocumentReader接着通过这个类来发起注册调用在这个之前调用 createReaderContext 来创建 XmlReaderContext。 XmlReaderContext public XmlReaderContext createReaderContext(Resource resource) {return new XmlReaderContext(resource, this.problemReporter, this.eventListener,this.sourceExtractor, this, getNamespaceHandlerResolver()); } public NamespaceHandlerResolver getNamespaceHandlerResolver() {if (this.namespaceHandlerResolver null) {this.namespaceHandlerResolver createDefaultNamespaceHandlerResolver();}return this.namespaceHandlerResolver; } protected NamespaceHandlerResolver createDefaultNamespaceHandlerResolver() {ClassLoader cl (getResourceLoader() ! null ? getResourceLoader().getClassLoader() : getBeanClassLoader());return new DefaultNamespaceHandlerResolver(cl); } public DefaultNamespaceHandlerResolver() {this(null, DEFAULT_HANDLER_MAPPINGS_LOCATION); } 逻辑很简单由于 spring 遵循 SRP(单一职责原则)所以类会比较多。 这个 DefaultNamespaceHandlerResolver 就是完成自定义标签扩展及解析很重要的一个类。在DEFAULT_HANDLER_MAPPINGS_LOCATION即 META-INF/spring.handlers 中会存放自定义标签相应的解析器以 keyvalue 形式存放其中 key 为 namespaceUrivalue 为对应的解析器的全限定性类名形式如下 http\://www.springframework.org/schema/aoporg.springframework.aop.config.AopNamespaceHandler 这里就完成了 XmlReaderContext 的创建接下来通过 documentReader 发起调用。 DefaultBeanDefinitionDocumentReader protected void doRegisterBeanDefinitions(Element root) {this.delegate createDelegate(getReaderContext(), root, parent);preProcessXml(root);parseBeanDefinitions(root, this.delegate);postProcessXml(root);this.delegate parent; } 核心逻辑 创建 delegateBeanDefinitionParserDelegate真正的解析 parseBeanDefinitions protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {if (delegate.isDefaultNamespace(root)) {NodeList nl root.getChildNodes();for (int i 0; i nl.getLength(); i) {Node node nl.item(i);if (node instanceof Element) {Element ele (Element) node;if (delegate.isDefaultNamespace(ele)) {parseDefaultElement(ele, delegate);}else {delegate.parseCustomElement(ele);}}}}else {delegate.parseCustomElement(root);} } 根据是否为默认名命空间将解析分为两个分支 parseDefaultElementparseCustomElement parseDefaultElement  public boolean isDefaultNamespace(Nullable String namespaceUri) {return !StringUtils.hasLength(namespaceUri) || BEANS_NAMESPACE_URI.equals(namespaceUri); } 默认的名命空间有两个条件 namespeceUri 不为 null 或 为http://www.springframework.org/schema/beans private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {importBeanDefinitionResource(ele);}else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {processAliasRegistration(ele);}else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {processBeanDefinition(ele, delegate);}else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {// recursedoRegisterBeanDefinitions(ele);} } 默认标签共四个import、alias、bean、beans。 parseCustomElement Nullable public BeanDefinition parseCustomElement(Element ele, Nullable BeanDefinition containingBd) {String namespaceUri getNamespaceURI(ele);if (namespaceUri null) {return null;}NamespaceHandler handler this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);if (handler null) {error(Unable to locate Spring NamespaceHandler for XML schema namespace [ namespaceUri ], ele);return null;}return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd)); } 核心逻辑 先利用 XmlReaderContext 中创建的 DefaultNamespaceHandlerResolver 解析 namespaceUri获取对应的 NamespaceHandler。 public NamespaceHandler resolve(String namespaceUri) {MapString, 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);}NamespaceHandler namespaceHandler (NamespaceHandler) BeanUtils.instantiateClass(handlerClass);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);}} } 核心逻辑 调用 getHandlerMappings加载 handlerMappingsLocation 下配置的 spring.handlers得到 java.util.Properties处理成 Map赋值给 handlerMappings接着根据 namespaceUri 从 handlerMappings 中去拿第一次如果能拿到为一个字符串即配置的解析器的全限定性类名加载这个类得到 Class接着实例化一个 NamespaceHandler 对象调用 init 方法这样就完成了自定义解析器的创建。 此处有一个优化就是类的加载和实例化只执行一次创建完实例对象后会放入 handlerMappings将原有的 value 值全限定性类名替换为具体的实例对象下一次遇到同样的namespaceUri 时执行 resolve直接从 handlerMappings 中查找到 NamespaceHandler 对象就返回了。 得到这个 NamespaceHandler调用 parse 方法完成具体对应标签的解析。 示例 以 aop 标签为例下面来看看对应的 AopNamespaceHandler 及解析方法。先来看看这个标签下的元素名称。 public void init() {// In 2.0 XSD as well as in 2.5 XSDsregisterBeanDefinitionParser(config, new ConfigBeanDefinitionParser());registerBeanDefinitionParser(aspectj-autoproxy, new AspectJAutoProxyBeanDefinitionParser());registerBeanDefinitionDecorator(scoped-proxy, new ScopedProxyBeanDefinitionDecorator());// Only in 2.0 XSD: moved to context namespace in 2.5registerBeanDefinitionParser(spring-configured, new SpringConfiguredBeanDefinitionParser()); } 每个标签下不同的元素名匹配不同的 Parser具体定义了几个 Parser都在此处进行实例化创建并将这些 BeanDefinitionParser 注册到父类 NamespaceHandlerSupport 的 parsers 中方便后续使用。 这里有一点注意就是实际扩展自定义标签实现自定义标签 NamespaceHandler 时并不需要直接实现 NamespaceHandler 接口继承 NamespaceHandlerSupport 即可。 以 aspectj-autoproxy 为例。 aop:aspectj-autoproxy/ 解析时遇到这个标签调用 parseCustomElement接着拿到具体的 handler发起 parse 调用调入 NamespaceHandlerSupport#parse 中根据解析出的节点名 aspectj-autoproxy获取对应的 BeanDefinitionParser此时为 AspectJAutoProxyBeanDefinitionParser。 Override Nullable public BeanDefinition parse(Element element, ParserContext parserContext) {AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);extendBeanDefinition(element, parserContext);return null; }public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(ParserContext parserContext, Element sourceElement) {BeanDefinition beanDefinition AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext.getRegistry(), parserContext.extractSource(sourceElement));useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);registerComponentIfNecessary(beanDefinition, parserContext); } 创建 XmlReaderContext 时传入的 sourceExtractor 为 NullSourceExtractor调用 extractSource 方法后返回 null。  Nullable public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Nullable Object source) {return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source); } Nullable private static BeanDefinition registerOrEscalateApcAsRequired(Class? cls, BeanDefinitionRegistry registry, Nullable Object source) {Assert.notNull(registry, BeanDefinitionRegistry must not be null);if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {BeanDefinition apcDefinition registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);if (!cls.getName().equals(apcDefinition.getBeanClassName())) {int currentPriority findPriorityForClass(apcDefinition.getBeanClassName());int requiredPriority findPriorityForClass(cls);if (currentPriority requiredPriority) {apcDefinition.setBeanClassName(cls.getName());}}return null;}RootBeanDefinition beanDefinition new RootBeanDefinition(cls);beanDefinition.setSource(source);beanDefinition.getPropertyValues().add(order, Ordered.HIGHEST_PRECEDENCE);beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);return beanDefinition; } 可以看到注册了一个名称为 AUTO_PROXY_CREATOR_BEAN_NAME 的 BeanDefinition。 private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, Nullable Element sourceElement) {if (sourceElement ! null) {boolean proxyTargetClass Boolean.parseBoolean(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE));if (proxyTargetClass) {AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);}boolean exposeProxy Boolean.parseBoolean(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE));if (exposeProxy) {AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);}} } 判断标签中是否存在 proxy-target-class、expose-proxy 两个属性存在添加到 BeanDefinition 的 PropertyValues 中。其中 proxy-target-class 对应 ProxyConfig.proxyTargetClass 属性控制在存在接口时是否采用 Cglib 作为切面增强。expose-proxy 对应 exposeProxy 属性控制在执行拦截方法 interceptor 时是否将当前 proxy 暴露出去即是否执行AopContext.setCurrentProxy(proxy);。 private void extendBeanDefinition(Element element, ParserContext parserContext) {BeanDefinition beanDef parserContext.getRegistry().getBeanDefinition(AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAME);if (element.hasChildNodes()) {addIncludePatterns(element, parserContext, beanDef);} }private void addIncludePatterns(Element element, ParserContext parserContext, BeanDefinition beanDef) {ManagedListTypedStringValue includePatterns new ManagedList();NodeList childNodes element.getChildNodes();for (int i 0; i childNodes.getLength(); i) {Node node childNodes.item(i);if (node instanceof Element) {Element includeElement (Element) node;TypedStringValue valueHolder new TypedStringValue(includeElement.getAttribute(name));valueHolder.setSource(parserContext.extractSource(includeElement));includePatterns.add(valueHolder);}}if (!includePatterns.isEmpty()) {includePatterns.setSource(parserContext.extractSource(element));beanDef.getPropertyValues().add(includePatterns, includePatterns);} } 可以看到 extendBeanDefinition 方法的作用就是解析 aop:aspectj-autoproxy 的子标签 aop:include name/最后将其作为 includePatterns 添加进 BeanDefinition 的 PropertyValues。 顺便说一句dubbo 框架中的自定义标签 dubbo:xxx 就是自定义标签扩展的一个应用。
http://www.zqtcl.cn/news/632780/

相关文章:

  • jsp网站空间网站开发北京 广告 手机网站
  • 郑州网站建设推广爱站网seo综合查询工具
  • 2017年网站开发用什么语言手游排行榜
  • 鞍山百度网站怎么制作建设部网站建造师公示
  • 建设部网站业绩补录营销型网站制作的方法
  • 建设网站的功能及目的是什么意思兰州网络优化seo
  • 用ps软件做ppt模板下载网站有哪些内容广州seo服务外包
  • 毕业设计论文网站开发需要多少湛江建站免费模板
  • 做豆制品的网站集团网站建设策划方案
  • 燕郊网站制作哈尔滨企业网站建站推荐
  • 本地网站做通用会员卡建立电子商务网站目的
  • ftp网站地图怎么做网站模板出售
  • 用rp怎么做网站导航菜单手机app制作入门教程
  • 国外创意网站市场营销在线课程
  • 怎么做点图片链接网站网站建设云解析dns有什么用
  • 重庆网站建设哪家公司哪家好企业 网站规划与网页设计word
  • 手机必备软件100个网站建设和优化排名
  • 天津公司网站怎样制作网页设计图片尺寸
  • 网站建设中模板代码网络营销推广公司哪家好
  • 百度免费建立网站搜索引擎推广效果
  • 网站建设分金手指排名十二建设内容管理网站的目的
  • 无锡网站策划制作网站的工具
  • 免费的网站开发软件百度做网站推广的费用
  • 汽车维修东莞网站建设怎么用阿里的域名 做网站
  • 网站怎么做免费cosy WordPress
  • wordpress 关闭自动更新青岛济南网站建设优化
  • 外贸网站推广平台哪个好如何建设手机端网站
  • linux新建网站巩义网站建设定制
  • 网站建设要什么软件有哪些北京seo
  • 空调设备公司网站建设wordpress 4.9