Spring4.3.x 浅析xml配置的解析过程(5)——解析自定义命名空间的标签

优秀的 Verilog/FPGA开源项目介绍(二十六)- ISP (图像信号处理) 介绍查看《ISP算法及架构分析介绍》今天项目的顺序就是先介绍几个关于ISP算法架构的项目,包括python、matlab、c等高级语言实现的ISP算法架构,最后介绍一个FPGA实现ISP的项目。openISPhttps://github.com/cruxopen/openISP项目介绍用python实现的ISP架构,该架构涉及到的知识如下:下图是最新实现的模块:主要模块如... 阅读详情

概述


在上一篇解析<bean>标签及其所有子标签我们详细探讨了如何使用<bean>标签来创建一个BeanDefintion对象。这一篇我们开始探讨一下spring如何处理其它命名空间的xml标签,比如spring扩展的http://www.springframework.org/schema/context、http://www.springframework.org/schema/p和http://www.springframework.org/schema/aop命名空间。

经过前面的探讨,我们知道XmlBeanDefinitionReader使用BeanDefinitionDocumentReader对象把Document对象中包含的配置信息转换成BeanDefinition对象并把它注册到BeanDefintionRegistry对象中。默认使用DefaultBeanDefinitionDocumentReader来操作Document对象。在DefaultBeanDefinitionDocumentReader的实现中,它的责任是遍历xml根节点下的子节点,并把处理bean标签和自定义命名空间的标签(比如aop:,context:,p:等)的细节委托给BeanDefinitionParserDelegate对象,BeanDefinitionParserDelegate才是真正解析配置文件的地方。

下面是DefaultBeanDefinitionDocumentReader对象使用BeanDefinitionParserDelegate对象来处理自定义命名空间的标签的入口,

    protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
        // 检查root节点的命名空间是否为默认命名空间
        // spring配置文件中默认的命名空间为"http://www.springframework.org/schema/beans"
        if (delegate.isDefaultNamespace(root)) {
            NodeList nl = root.getChildNodes();
            // 遍历root节点下的所有子节点
            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);
        }
    }

parseBeanDefinitions方法的主要事情是区分节点标签是否是默认命名空间的标签,以及遍历根节点下的子节点。在这里对于任何一个节点,如果是默认命名空间的则调用DefaultBeanDefinitionDocumentReader方法parseDefaultElement处理,否则调用BeanDefinitionParserDelegate 的parseCustomElement方法来处理。这篇文章的主题是探讨spring如何解析自定义命名空间的标签,因此我们的入口是parseCustomElement方法,如下是这个方法的源代码。

    public BeanDefinition parseCustomElement(Element ele) {
        return parseCustomElement(ele, null);
    }

parseCustomElement(Element ele)方法把处理节点的任务传递给parseCustomElement(Element ele, BeanDefinition containingBd)方法,这个方法的源码如下。

    public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
        // 获取命名空间的uri
        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的parse方法处理节点
        return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
    }

parseCustomElement(Element ele, BeanDefinition containingBd)首先通过节点的命名空间uri字符串获取命名空间处理器NamespaceHandler对象,然后调用处理器的parse方法处理节点。spring定义了很多命名空间和它们对于的处理器类,因此,我们在这里需要清楚的是如何获取NamespaceHandler对象。

获取命名空间处理器NamespaceHandler对象

下面是spring定义的NamespaceHandler接口的代码。

public interface NamespaceHandler {

    /**
     * DefaultBeanDefinitionDocumentReader实例化一个NamespaceHandler对象的时候会调用此方法
     */
    void init();

    /**
     * 解析指定的的Element对象,并返回一个BeanDefinition对象。
     */
    BeanDefinition parse(Element element, ParserContext parserContext);

    /**
     * 解析指定的节点,并装饰指定的BeanDefinitionHolder对象,最后返回一个已经装饰的BeanDefinitionHolder对象。
     * 这个方法在parse方法之后被调用
     */
    BeanDefinitionHolder decorate(Node source, BeanDefinitionHolder definition, ParserContext parserContext);

}

Spring定义了NamespaceHandlerResolver接口来获取命名空间处理器,这个接口的定义如下。

public interface NamespaceHandlerResolver {

    /**
     * 解析命名空间的URI字符串并返回一个对应的NamespaceHandler对象,如果没有找到,则返回null
     */
    NamespaceHandler resolve(String namespaceUri);

}

NamespaceHandlerResolver 接口只定义了一个方法,并且Spring给出了一个默认的实现,那就是DefaultNamespaceHandlerResolver类,我们来看看这个类的resolve(String namespaceUri)方法,源代码如下。

    @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);
                // 检查handlerClass 是否实现了NamespaceHandler接口
                if (!NamespaceHandler.class.isAssignableFrom(handlerClass)) {
                    throw new FatalBeanException("Class [" + className + "] for namespace [" + namespaceUri +
                            "] does not implement the [" + NamespaceHandler.class.getName() + "] interface");
                }
                // 实例化NamespaceHandler对象
                NamespaceHandler namespaceHandler = (NamespaceHandler) BeanUtils.instantiateClass(handlerClass);
                // 初始化NamespaceHandler对象
                namespaceHandler.init();
                // 把NamespaceHandler对象缓存到handlerMappings对象中
                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);
            }
        }
    }

DefaultNamespaceHandlerResolver的resolve方法通过调用getHandlerMappings()方法获得NamespaceHandler对象与命名空间URI的映射表,并从这个映射表中取到并返回对应的NamespaceHandler对象。resolve方法的重点就在于NamespaceHandler对象映射表的获取,下面看看getHandlerMappings()方法的源代码。

    private Map<String, Object> getHandlerMappings() {
        if (this.handlerMappings == null) {
            synchronized (this) {
                if (this.handlerMappings == null) {
                    try {
                        // 这里的handlerMappingsLocation默认为"META-INF/spring.handlers"
                        Properties mappings =
                                PropertiesLoaderUtils.loadAllProperties(this.handlerMappingsLocation, this.classLoader);
                        if (logger.isDebugEnabled()) {
                            logger.debug("Loaded NamespaceHandler mappings: " + mappings);
                        }
                        // 创建一个线程安全的Map对象
                        Map<String, Object> handlerMappings = new ConcurrentHashMap<String, Object>(mappings.size());
                        // 把Properties对象中的key-value复制到handlerMappings中国
                        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;
    }

getHandlerMappings在第一次调用的时候会通过DefaultNamespaceHandlerResolver的handlerMappingsLocation属性值(默认为META-INF/spring.handlers)获取classes路径和所有jar包中有的相应资源,我们来看看PropertiesLoaderUtils是怎么使用 loadAllProperties(String resourceName, ClassLoader classLoader)加载资源的,代码如下。

    public static Properties loadAllProperties(String resourceName, ClassLoader classLoader) throws IOException {
        Assert.notNull(resourceName, "Resource name must not be null");
        ClassLoader classLoaderToUse = classLoader;
        if (classLoaderToUse == null) {
            // 获取默认的ClassLoader对象
            classLoaderToUse = ClassUtils.getDefaultClassLoader();
        }
        // 使用ClassLoader对象来加载class路径和所有jar包下所匹配的资源
        Enumeration<URL> urls = (classLoaderToUse != null ? classLoaderToUse.getResources(resourceName) :
                ClassLoader.getSystemResources(resourceName));
        Properties props = new Properties();
        while (urls.hasMoreElements()) {
            URL url = urls.nextElement();
            URLConnection con = url.openConnection();
            // 为JNLPCachedJarURLConnection启动缓存
            ResourceUtils.useCachesIfNecessary(con);

            InputStream is = con.getInputStream();
            try {
                if (resourceName.endsWith(".xml")) {
                    // 加载xml文件
                    props.loadFromXML(is);
                } else {
                    // 加载properties文件
                    props.load(is);
                }
            } finally {
                is.close();
            }
        }
        return props;
    }

loadAllProperties方法从classes路径下和所有jar包中获取所有匹配的资源,并把这些资源文件的内容都保存到同一个Properties对象中作为loadAllProperties方法的返回值。

Spring自定义的NamespaceHandler对象

我们看看Spring都创建了哪些spring.handlers文件及其内容。
a. spring-beans包下的

http\://www.springframework.org/schema/c=org.springframework.beans.factory.xml.SimpleConstructorNamespaceHandler
http\://www.springframework.org/schema/p=org.springframework.beans.factory.xml.SimplePropertyNamespaceHandler
http\://www.springframework.org/schema/util=org.springframework.beans.factory.xml.UtilNamespaceHandler

b. spring-context包下的

http\://www.springframework.org/schema/context=org.springframework.context.config.ContextNamespaceHandler
http\://www.springframework.org/schema/jee=org.springframework.ejb.config.JeeNamespaceHandler
http\://www.springframework.org/schema/lang=org.springframework.scripting.config.LangNamespaceHandler
http\://www.springframework.org/schema/task=org.springframework.scheduling.config.TaskNamespaceHandler
http\://www.springframework.org/schema/cache=org.springframework.cache.config.CacheNamespaceHandler

c. spring-aop包下的

http\://www.springframework.org/schema/aop=org.springframework.aop.config.AopNamespaceHandler

d. spring-tx包下的

http\://www.springframework.org/schema/tx=org.springframework.transaction.config.TxNamespaceHandler

e. spring-jdbc包下的

http\://www.springframework.org/schema/jdbc=org.springframework.jdbc.config.JdbcNamespaceHandler

e. spring-webmvc包下的

http\://www.springframework.org/schema/mvc=org.springframework.web.servlet.config.MvcNamespaceHandler

spring.handlers文件中=号左边的是命名空间uri,=号右边的是命名空间处理器类的全名称。

我们看看p命名空间的处理器SimplePropertyNamespaceHandler类的源码,如下。

public class SimplePropertyNamespaceHandler implements NamespaceHandler {

    private static final String REF_SUFFIX = "-ref";


    @Override
    public void init() {
    }

    @Override
    public BeanDefinition parse(Element element, ParserContext parserContext) {
        parserContext.getReaderContext().error(
                "Class [" + getClass().getName() + "] does not support custom elements.", element);
        return null;
    }

    @Override
    public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder definition, ParserContext parserContext) {
        // p命名空间只处理属性
        if (node instanceof Attr) {
            Attr attr = (Attr) node;
            String propertyName = parserContext.getDelegate().getLocalName(attr);
            String propertyValue = attr.getValue();
            // 获取BeanDefinition的MutablePropertyValues对象
            MutablePropertyValues pvs = definition.getBeanDefinition().getPropertyValues();
            if (pvs.contains(propertyName)) {
                parserContext.getReaderContext().error("Property '" + propertyName + "' is already defined using " +
                        "both <property> and inline syntax. Only one approach may be used per property.", attr);
            }
            if (propertyName.endsWith(REF_SUFFIX)) {
                // 获取属性名称
                propertyName = propertyName.substring(0, propertyName.length() - REF_SUFFIX.length());
                // 设置为bean引用
                pvs.add(Conventions.attributeNameToPropertyName(propertyName), new RuntimeBeanReference(propertyValue));
            } else {
                pvs.add(Conventions.attributeNameToPropertyName(propertyName), propertyValue);
            }
        }
        return definition;
    }

}

再看看aop命名空间的处理器AopNamespaceHandler 类的源码,如下。

public class AopNamespaceHandler extends NamespaceHandlerSupport {

    @Override
    public void init() {
        // 注册config标签的的解析器
        registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
        // 注册aspectj-autoproxy标签的解析器
        registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
        // 注册scoped-proxy标签的装饰器
        registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());

        // 注册spring-configured标签的解析器
        registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
    }

}

上面两个例子是spring创建NamespaceHandler实现类的两种方式,第一种是直接实现NamespaceHandler接口提供的方法,这种方式适合于命名空间中标签只有一个或者解析标签和属性的过程很简单,比如p命名空间;第二种是继承抽象类NamespaceHandlerSupport 并实现init方法,在init方法中注册标签的解析器和装饰器以及属性的装饰器,spring中大多数命名空间处理器都使用这种方式。

NamespaceHandlerSupport向子类提供了三个方法分别用于注册标签的解析、标签的装饰器、属性的装饰器,如下。

    /**
     * 注册标签的解析器BeanDefinitionParser对象
     */
    protected final void registerBeanDefinitionParser(String elementName, BeanDefinitionParser parser) {
        this.parsers.put(elementName, parser);
    }

    /**
     * 注册标签的装饰器BeanDefinitionDecorator对象
     */
    protected final void registerBeanDefinitionDecorator(String elementName, BeanDefinitionDecorator dec) {
        this.decorators.put(elementName, dec);
    }

    /**
     * 注册属性的装饰器BeanDefinitionDecorator对象
     */
    protected final void registerBeanDefinitionDecoratorForAttribute(String attrName, BeanDefinitionDecorator dec) {
        this.attributeDecorators.put(attrName, dec);
    }

spring为解析标签自定义了一个BeanDefinitionParser接口,源码如下。

public interface BeanDefinitionParser {

    /**
     * 解析指定的节点元素,并返回一个已经注册到BeanDefinitionRegistry对象(BeanDefinition注册表)中的BeanDefinition对象。
     */
    BeanDefinition parse(Element element, ParserContext parserContext);

}

spring还为装饰标签和属性定义了一个BeanDefinitionDecorator接口,源码如下。

public interface BeanDefinitionDecorator {

    /**
     * 根据指定Node对象装饰BeanDefinitionHolder对象,这个Node对象可以是属性,即Attr对象,
     * 也可以是标签元素,即Element对象
     * 最后返回一个装饰好了的BeanDefinitionHolder 对象
     */
    BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder definition, ParserContext parserContext);

}

看到这里,我们再来说说NamespaceHandler和BeanDefinitionParser 以及BeanDefinitionDecorator二者的关系。
a. 对NamespaceHandler来说,它们可有可无。不过对于spring框架本身来说,这样的设计提高了spring的可维护性、可扩展性和易读性。
b. 对BeanDefinitionParser 和BeanDefinitionDecorator来说,它们必须受NamespaceHandler的管控和调度,否则它们将一无是处。

总结


(1)spring通过NamespaceHandler对象来解析自定义标签和属性,同时也用这个对象来装饰BeanDefinitionHolder对象。

(2)DefaultNamespaceHandlerResolver用于管理NamespaceHandler实现类。因此可以从DefaultNamespaceHandlerResolver中根据命名空间uri获取到对应的NamespaceHandler对象。

(3)NamespaceHandler实现类需要在/META-INF/spring.handler文件中注册,否则不能被DefaultNamespaceHandlerResolver对象加载。

(4)命名空间中有多个标签需要解析和装饰,命名空间处理器类最好继承NamespaceHandlerSupport ,并为标签分别定义BeanDefinitionParser解析器或者BeanDefinitionDecorator装饰器。

100天精通Python(可视化篇)——第109天:Pyecharts绘制各种常用地图(参数说明+代码实战) 阅读详情

相关推荐

直流电机双闭环调速系统MATLAB仿真

Chopper-Fed DC Motor Drive This example shows a Chopper-Fed DC Motor Drive. Description The DC motor is fed by the DC source through a chopper which consists of GTO thyristor and free-wheeling diode ...

飞行动力的博客 2万+

Spring4.3 学习笔记

目录 Spring简介 1. Spring是开源的轻量级框架 2. Spring的两个核心——IoC和AOP 3. Spring是一站式框架 Spring的IoC操作 一、IoC底层原理 二、IoC入门案例 1.导入jar包 2.创建POJO类,在类中创建方法 3.创建Spring配置文件,配置需要创建的类 4.编写测试代码 三、Spring的bean管理(XML方式) ...

Luvean的博客 906

Altium Designer操作技巧(12)——如何进行邮票孔拼版?

【摘要】本文详细介绍了PCB设计中邮票孔拼板的全流程操作方法。首先解释了邮票孔拼板的定义、核心目的(提高贴片效率、方便生产)和适用场景(异形板、V-CUT无法实现的情况)。重点阐述了关键设计参数,包括孔径、数量、间隙等规范要求,并提供了两种具体操作方案:传统复制粘贴法和新版阵列放置法。文章通过图文详细演示了从PCB复制、邮票孔添加、板框定义到定位孔和Mark点设置的完整步骤,最后强调了对称性、非金属化孔等设计要点,以及需要与板厂确认工艺参数等注意事项。

u012526819的博客 1676

Spring4.3.x 浅析xml配置的解析过程(6)——解析context命名空间之property-placeholder和property-override标签

概述在上一篇解析自定义命名空间的标签 中,我们已经知道解析自定义命名空间的标签需要用到NamespaceHandler接口的实现类,并且知道spring是如何获取命名空间对应的命名空间处理器对象的。因此我们很容易就能在spring-context包下的META-INF/spring.handlers文件中找到http://www.springframework.org/schema/context命

chyohn的博客 3171

ENSP Pro VXLAN EVPN分布式网关部署配置

在BGP EVPN方式部署分布式网关的场景中,控制平面的流程包括VXLAN隧道建立、MAC地址动态学习;转发平面的流程包括同子网已知单播报文转发、同子网BUM报文转发、跨子网报文转发。该方式实现的功能全面,支持主机IP路由通告、主机MAC地址通告、主机ARP通告,可以直接使能ARP广播抑制功能。如果在VXLAN网络中采用分布式网关,推荐使用此方式。对比集中式网关,分布式网关的arp条目比集中式网关的arp条目少,分布式网关只学习租户侧的arp条目,不学习网络侧的arp条目。

qq2353177176的博客 4559

IGBT模块封装中的银烧结技术:为什么特斯拉和比亚迪都在用这种黑科技?

本文深入解析了IGBT模块封装中的银烧结技术,揭示了其作为功率半导体封装工艺关键升级的原因。该技术通过低温烧结形成高熔点、高导热导电的银连接层,显著提升了模块的功率循环寿命、散热能力和高温工作稳定性,这正是特斯拉、比亚迪等行业巨头采用此项黑科技以释放电动汽车电驱系统极致性能的核心所在。

yhn4567890的博客 833

spring4笔记----PropertyOverrideConfigureer 重写占位符配置器(图)

     

weixin_34128237的博客 205

KUKA-外部自动运行模板程序——个人设计模式&思路

用于说明KUKA与西门子PLC外部自动交互模板的设计思路与使用流程

qq_39024187的博客 5612

Spring配置:用context:property-placeholder替换PropertyPlaceholderConfigurer

有时候需要从properties文件中加载配置,以前的方式是这样的: classpath*:/spring/jdbc.properties 最近发现这样也可以,代码更整洁: 在bean定义中依然可以通过“${}”这种方式来去值:

专栏 9131

【BAT32G113-仿真器及脱机烧录器教程-A3-2024/9/19】

提示:此壁纸收集于互联网,如有侵权,请联系作者!今日下班,闲来无事,就与生活中在乎的人闲日常,互相彼此增进一些友谊或爱意情愫!在座的朋友看到这里,有时间,抽抽空,多多联系一下,身边重要的人哟!四种指示灯和一个按钮:MODE->代表红色POWER->代表黄色ACTIVE->代表蓝色STATUS->代表XX(不记得了)黑色按钮:按键上电,会进入升级模式,这里我们一般默认不需要改变!仿真工具-ICE8-PRO介绍隶属于产品分支里。烧写工具-CMS-WRITER8 LITE介绍点击。

星新计划的博客 8265

bugku渗透测试4-writeup

三、对这个主机进行全端口的扫描,发现存在22000 ssh端口,那么可以联想到时redis写入公钥来连接主机。又来了一个新的靶场,这个靶场打下来我觉得关键就是信息收集,走了很多的弯路。八、最后一个flag是要去看cms的数据库里面,这个数据库是sqlite。把这个数据库下载下来,登录密码是加密的,就直接用token。一、入口的漏洞是在登录的时候去抓包,修改action的值。六、没想到这个第一台机器的密码,在第二台里面。七、扫描第一台主机、使用之前的密码连接成功。获取最后一台主机的root密码。

vsdfbhsdhsdfh的博客 1297

Java最新Java 冒泡排序详解,一分钟理解冒泡排序,快手java面试算法题

笔者已经把面试题和答案整理成了面试专题文档本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录需要这份系统化的资料的朋友,可以点击这里获取ums/4f45ff00ff254613a03fab5e56a57acb)收录**需要这份系统化的资料的朋友,可以点击这里获取。

2401_84585440的博客 629

基于模糊神经网络实现水质评价预测 - Matlab源码

首先定义输入层、隐含层和输出层的节点数,并初始化权重和阈值,然后开始训练模型,在每轮训练中通过比较模型的输出值与实际值的误差来更新权重和阈值,直到误差达到最小值,为了提高模型的性能,我们可以采用交叉验证等技术进行优化。首先需要准备好数据集,使用的是嘉陵江的水质监测数据集,数据集包含了多个指标,如 pH 值、溶解氧、总氮、总磷等,以及相应的水质等级,我们需要将数据集分为训练集和测试集。在当今环境日益恶化的情况下,水质监测变得越来越重要,模糊神经网络作为一种新型的。

weixin_50547796的博客 147

Spring4.3.x xml配置文件搜索和解析过程

绪论 spring在创建BeanFactory时会把xml配置文件和注解信息转换为一个个BeanDefinition对象,BeanDefinition对象存储的是单个bean的配置信息,比如依赖类、scope、是否延迟加载等等。因此,研究配置文件的解析过程,对学习spring也是重要的一点。 下面我们通过XmlWebApplicationContext来研究Spring配置文件的解析。 获取

chyohn的博客 1485

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

Spring IoC容器初始化源码(4)—<context:component-scan/>标签解析、spring.components扩展点、自定义Spring命名空间扩展点【两万字】

基于最新Spring 5.x,介绍了包括< context:component-scan/>扩展标签解析源码、spring.components扩展点、自定义Spring命名空间扩展点!

终生学习践行者 3059

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

Spring5.x Transaction 自定义事务标签

1、自定义事务标签XML配置 <tx: annotation-driven transaction-manager="transactionManager" mode="aspectj "/> 2、自定义事务标签命名空间处理器TxNamespaceHandler public class TxNamespaceHandler extends NamespaceHandl...

lemon 1317

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

【Spring实战】----Spring配置文件的解析

一、背景知识 Spring的核心的核心就是bean的配置及管理,至Spring最新发布的版本4.3.2已经有三种方式可以配置bean: 1)在XML中进行显示配置 2)在Java中进行显示配置 3)隐式的bean发现机制和自动装配 上述三种配置不展开说明,而且目前用的较多的是第3种(当然XML配置文件的使用仍然占据了不可替代的位置),可参考《Spring in Aciton 第四版》。但

honghailiang的专栏 1万+

spring5.x自定义标签学习之解析原理

引言:在上一篇了解到spring的自定义标签的创建过程,接下下来我们看看自定义标签的解析原理。有不对的地方请大佬留言指出哈。 1、解析源入口:org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#parseBeanDefinitions protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegat

w952904879的博客 228

spring xml 配置文件中标签的解析

一个springmvc配置文件的例子为: <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:con...

weixin_30414155的博客 155

spring xml配置文件头解析

一直以来,写Spring配置文件,都是把其他配置文件的头拷贝过来,最多改改版本号,也不清楚哪些是需要的,到底是干嘛的。今天整理一下,拒绝再无脑copy。 一、Spring配置文件常见的配置头 &lt;?xml version="1.0" encoding="UTF-8"?&gt; &lt;beans xmlns="http://www.springframework.org/schema...

W.J.H. 1579

Spring5.x之XmlBeanFactory源码解析-解析自定义标签(四)

Spring5.x之XmlBeanFactory源码解析-XmlBeanFactory整体概览(一) Spring5.x之XmlBeanFactory源码解析-解析前准备(二) Spring5.x之XmlBeanFactory源码解析-解析默认标签(三) 我们已经完成了分析默认标签的解析与提取过程,再次看下默认标签解析函数的起始函数: BeanDefinition...

lemon 319

Spring 系列之 Spring 源码笔记:解析自定义标签【八】

在很多情况下,需要为系统提供可配置化支持,简单的做法可以直接基于 Spring 的标准 bean 来配置,但配置较为复杂或者需要更多丰富控制的时候,会显得非常笨拙。一般的做法会使用原生态的方式去解析定义好的 XML 文件,然后转化为配置对象。这种方式当然可以解决所有问题,但是实现起来比较繁琐,特别是在配置非常复杂的时候,解析工作是一个不得不考虑的负担。

fei1234456的博客 632

Dubbo 3.x 源码解析 - Dubbo xml配置的加载源码

Dubbo 3.x中XML配置的加载主要是依赖于Spring框架的,它利用了Spring的自定义标签解析机制来解析Dubbo特定的XML配置。

qq_33240556的博客 507

Spring中tx命名空间和配置注解工作原理浅析

Spring中tx命名空间和配置注解工作原理浅析   在使用Spring时,对于一些功能的配置可以通过Spring提供的XML命名空间进行配置,也可以通过提供的注解进行配置。这两种方式都是等价的,它们背后对应的工作原理是什么呢? 以事务管理为例:(以下代码来自Spring的API文档) @EnableTransactionManagement注解启用了事务管理功能。   @Confi...

jybzjf的专栏 979

Spring XML 配置文件的命名空间

1、命名冲突(不使用命名空间有啥问题) 在 XML 中,元素名称是由开发者定义的,当两个不同的文档使用相同的元素名时,就会发生命名冲突。 这个 XML 文档携带着某个表格中的信息: <table> <tr> <td>Apples</td> <td>Bananas</td> </tr> </table> 这个 XML 文档携带有关桌子的信息(一件家具): <table>

lihuihui01的博客 711

Spring学习日记【3】——配置文件Xml的命名空间

Spring Bean配置文件——Xml的命名空间 下面是一份非常常见的xml文件。 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.o

ColdWindHA的博客 349
上一篇: Spring4.3.x 浅析xml配置的解析过程(4)——解析bean标签及其所有子标签
下一篇: Spring4.3.x 浅析xml配置的解析过程(6)——解析context命名空间之property-placeholder和property-override标签
chyohn
博客等级 码龄10年 278粉丝 44原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值