欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

spring拓展之如何定義自己的namespace

 更新時間:2021年09月26日 11:00:45   作者:試水流連  
這篇文章主要介紹了spring拓展之如何定義自己的namespace方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

spring拓展 定義自己的namespace

1.查看源碼認識spring是怎么加載xml配置的

1.1 spring是怎么創(chuàng)建對象的?

查看spring beanFactory的繼承關系

這里寫圖片描述

通過查看源碼可以得知,BeanFactory 中的對象創(chuàng)建是實際是根據RootBeanDefinition創(chuàng)建的, 在AbstractAutowireCapableBeanFactory中有具體的實現(xiàn),包括創(chuàng)建實例,

利用Spring拓展

java的內省實現(xiàn)BeanWrapperImpl,創(chuàng)建對象的包裝類,使用反射給對象填充屬性,并實現(xiàn)依賴注入DI 。具體可以自行參閱源碼。

public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
    .....
    protected abstract Object createBean(String beanName, RootBeanDefinition mbd, Object[] args)
            throws BeanCreationException;
}

這里寫圖片描述

而RootBeanDefination定義的是什么呢?查看AbstractBeanDefination類。

這里寫圖片描述

可以看到這里就是Spring對對象屬性的封裝,包括類名,屬性,加載策略等等,其實也就是我們在xml里 配置的對象。

1.2 spring是怎么將xml里配置的對象讀到BeanFactory中的?

在查看spring容器的源碼時,得知spring 是使用 org.springframework.beans.factory.xml.XmlBeanDefinitionReader 進行xml解析的

    public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
        .....
        protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
                    throws BeanDefinitionStoreException {
                try {
                    //讀取xml
                    Document doc = doLoadDocument(inputSource, resource);
                    //解析并注冊xml中定義的BeanDefination
                    return registerBeanDefinitions(doc, resource);
                }
                catch (BeanDefinitionStoreException ex) {
                    xxx
                }
            }
        .....
    }

接下來查看對dom 解析部分的源碼

public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocumentReader {
@Override
    public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
        this.readerContext = readerContext;
        logger.debug("Loading bean definitions");
        Element root = doc.getDocumentElement();
        doRegisterBeanDefinitions(root);
    }
    protected void doRegisterBeanDefinitions(Element root) {
        //為了實現(xiàn)進行遞歸解析
        BeanDefinitionParserDelegate parent = this.delegate;
        this.delegate = createDelegate(getReaderContext(), root, parent);
        if (this.delegate.isDefaultNamespace(root)) {
            //對profile的支持
            String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
            if (StringUtils.hasText(profileSpec)) {
                String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
                        profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
                if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
                    return;
                }
            }
        }
        preProcessXml(root);
        //開始解析dom樹
        parseBeanDefinitions(root, this.delegate);
        postProcessXml(root);
        this.delegate = parent;
    }
    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)) {
                        //spring的基礎命名元素解析(import、bean、beans、alias)其中在
                        //beans嵌套時會進行遞歸解析
                        parseDefaultElement(ele, delegate);
                    }
                    else {
                        //拓展元素解析
                        delegate.parseCustomElement(ele);
                    }
                }
            }
        }
        else {
            delegate.parseCustomElement(root);
        }
    }
}

查看spring是怎么實現(xiàn)拓展元素的解析的

public class BeanDefinitionParserDelegate {
    public BeanDefinition parseCustomElement(Element ele) {
        return parseCustomElement(ele, null);
    }
    public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
        //獲取當前節(jié)點命名空間URI
        String namespaceUri = getNamespaceURI(ele);
        //根據命名空間解析到自定義的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;
        }
        //使用拓展的Handler對當前節(jié)點進行解析
        return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
    }
}

其中NamespaceHandlerResolver 會去查找當前項目中classpath 下的META-INF目錄下所有文件名為 spring.handlers配置文件,定位到自定義namespace的解析器實現(xiàn)類。

其中在namespace 的處理器中可以通過進行BeanDefination的注冊,注冊過的BeanDefination會用來給BeanFactory創(chuàng)建對象使用,將解析好的BeanDefination注冊到parserContext.getRegistry()中即可。其實DefaultListableBeanFactory 就是一個BeanDefinitionRegistry。

@Override
    public BeanDefinition parse(Element element, ParserContext parserContext) {
        ....
        parserContext.getRegistry().registerBeanDefinition(beanName, mbd);
    }

2.定義自己的namespace

2.1 定義schema約束xsd文件

將自定義的xsd文件放到項目的 META-INF 目錄下。

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xsd:schema xmlns="http://xxx.xxx.com/schema/myns"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    xmlns:beans="http://www.springframework.org/schema/beans"
    xmlns:tool="http://www.springframework.org/schema/tool"
    targetNamespace="http://xxx.xxx.com/schema/myns">
    <xsd:import namespace="http://www.w3.org/XML/1998/namespace"/>
    <xsd:import namespace="http://www.springframework.org/schema/beans"/>
    <xsd:import namespace="http://www.springframework.org/schema/tool"/>
    <xsd:annotation>
        <xsd:documentation><![CDATA[ Namespace support for the myns test. ]]></xsd:documentation>
    </xsd:annotation>
    <xsd:complexType name="mybeanType">
        <xsd:attribute name="id" type="xsd:ID">
            <xsd:annotation>
                <xsd:documentation><![CDATA[ The unique identifier for a bean. ]]></xsd:documentation>
            </xsd:annotation>
        </xsd:attribute>
        <xsd:attribute name="name" type="xsd:string" use="required">
            <xsd:annotation>
                <xsd:documentation><![CDATA[ The mybean name. ]]></xsd:documentation>
            </xsd:annotation>
        </xsd:attribute>
        <xsd:attribute name="class" type="xsd:string" use="required">
            <xsd:annotation>
                <xsd:documentation><![CDATA[ The version. ]]></xsd:documentation>
            </xsd:annotation>
        </xsd:attribute>
    </xsd:complexType>
    <xsd:element name="mybean" type="mybeanType">
        <xsd:annotation> 
            <xsd:documentation><![CDATA[ The mybean config ]]></xsd:documentation> 
        </xsd:annotation>
    </xsd:element>
</xsd:schema>

更多xsd寫法可以參閱xml的相關資料。

2.2創(chuàng)建自定義namespace的NamespaceHandler

使用NamespaceHandlerSupport來實現(xiàn)我們定義的NamespaceHandler。在init時去提供具體的標簽的 解析器。

BeanDefinitionParser

public class MybeanParser implements BeanDefinitionParser {
    @Override
    public BeanDefinition parse(Element element, ParserContext parserContext) {
        RootBeanDefinition mbd =  new RootBeanDefinition();
        mbd.setBeanClassName(element.getAttribute("class"));
        String beanName = element.getAttribute("id");
        MutablePropertyValues mutablePropertyValues = new MutablePropertyValues();
        mutablePropertyValues.add("name", element.getAttribute("name"));
        mbd.setPropertyValues(mutablePropertyValues);
        parserContext.getRegistry().registerBeanDefinition(beanName, mbd);
        return mbd;
    }
}

實現(xiàn)自定義的NamespaceHandler

public class MynsNameSpaceHandler extends NamespaceHandlerSupport{
    @Override
    public void init() {
        registerBeanDefinitionParser("mybean", new MybeanParser());
    }
}

這里的mybean是myns namespace下的元素標簽的具體的解析實現(xiàn)

如:

<myns:mybean></myns:mybean>

2.3配置自定義的NamespaceHandler映射

在META-INF下創(chuàng)建文件 spring.handlers

http\://xxx.xxx.com/schema/myns=com.xxx.MynsNameSpaceHandler

2.4使用自定義的Namespace

<?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:myns="http://xxx.xxx.com/schema/myns"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://xxx.xxx.com/schema/myns http://xxx.xxx.com/schema/myns.xsd
        ">
        <myns:mybean class="com.xxx.People" id="mybean123" name="testMybean"></myns:mybean>
</beans>

2.5測試

public class MybeanNamespaceTestCase {
    @SuppressWarnings("resource")
    @Test
    public void testGetBean(){
        ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext(new String[]{"myapp.xml"},false);
        ac.setValidating(false);
        ac.refresh();
        People bean = ac.getBean("mybean123",People.class);
        System.out.println(bean.getName());
    }
}

這里設置ac.setValidating(false); 是因為如果開啟xml約束檢查,需要配置schema的位置,

也是在META-INF 下新建spring.schemas

并加入:

http\://xxx.xxx.com/schema/myns.xsd=META-INF/myns.xsd

這樣spring 在xml解析時會調用org.springframework.beans.factory.xml.PluggableSchemaResolver

進行獲取schema文件進行約束檢查,

這樣配置完畢后就可以ac.setValidating(true);啦,如果文件內容不符合規(guī)范,會啟動時拋出異常。

此外,如果想要在使用過程開發(fā)工具能夠像使用spring 自身的一些配置時有提升功能,可以將schema文件

上傳到文件服務器上,能夠通過http 訪問到xsi:schemaLocation的地方,或者配置開發(fā)工具中的xml 約束映射,將地址映射到本 地磁盤中,這樣就能

這里寫圖片描述

這里寫圖片描述

spring-namespace實現(xiàn)自定義標簽類

介紹如何通過spring namespace的方式進行bean的配置

最終要達到的目的如下:

<?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:user="http://www.wuxueyou.cn/schema/user"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.wuxueyou.cn/schema/user http://www.wuxueyou.cn/schema/user.xsd">
 
    <user:self-user id="user2" userId="12" name="aaa"/>
    <bean id="user1" class="com.xueyou.User">
        <property name="userId" value="33"/>
        <property name="name" value="xiaoming"/>
    </bean>
</beans>

好,下面上貨。

1.配置java bean

2.編寫xsd文件

3.編寫B(tài)eanDefinationParse標簽解析類

4.編寫調用標簽解析類的NamespaceHandler類

5.編寫spring.handlers和spring.schemas供spring讀取

6.在spring中使用

目錄結構

1.配置java Bean

package com.xueyou; 
public class User {
    private int userId;
    private String name; 
    public User() {
    }
 
    public int getUserId() {
        return userId;
    }
 
    public void setUserId(int userId) {
        this.userId = userId;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    @Override
    public String toString() {
        return "User{" +
                "userId='" + userId + '\'' +
                ", name='" + name + '\'' +
                '}';
    }
}

2.編寫xsd文件

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns="http://www.wuxueyou.cn/schema/user"
            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            xmlns:beans="http://www.springframework.org/schema/beans"
            targetNamespace="http://www.wuxueyou.cn/schema/user"
            elementFormDefault="qualified">
    <xsd:import namespace="http://www.springframework.org/schema/beans"
                schemaLocation="http://www.springframework.org/schema/beans/spring-beans.xsd"/>
    <xsd:element name="self-user">
        <xsd:complexType>
            <!--這里的最外層的id是spring用的,用來定義bean的名稱用的,不要和類中的id混淆了-->
            <xsd:attribute name="id" type="xsd:string" use="required"/>
            <xsd:attribute name="userId" type="xsd:int" use="required"/>
            <xsd:attribute name="name" type="xsd:string" use="required"/>
        </xsd:complexType>
    </xsd:element>
</xsd:schema>

3.編寫B(tài)eanDefinationParse標簽解析類

package com.xueyou.parser; 
import com.xueyou.User;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractSimpleBeanDefinitionParser;
import org.w3c.dom.Element;
 
public class UserDefinationParser extends AbstractSimpleBeanDefinitionParser {
    @Override
    protected Class<?> getBeanClass(Element element) {
        return User.class;
    }
 
    @Override
    protected void doParse(Element element, BeanDefinitionBuilder builder) {
        int userId = Integer.valueOf(element.getAttribute("userId"), 0);
        String name = element.getAttribute("name");
        builder.addPropertyValue("userId", userId);
        builder.addPropertyValue("name", name);
    }
}

4.編寫調用標簽解析類的NamespaceHandler類

package com.xueyou.handler; 
import com.xueyou.parser.UserDefinationParser;
import org.springframework.beans.factory.xml.NamespaceHandlerSupport; 
public class UserNamespaceHandler extends NamespaceHandlerSupport {
    public void init() {
        registerBeanDefinitionParser("self-user", new UserDefinationParser());
    }
}

5.編寫spring.handlers和spring.schemas以供spring讀取

spring.handlers

http\://www.wuxueyou.cn/schema/user=com.xueyou.handler.UserNamespaceHandler

spring.schemas

http\://www.wuxueyou.cn/schema/user.xsd=namespace/user.xsd

6.打包

首先把剛才的打成一個jar包,需要注意在maven的plugin中添加如下內容, 這個shade插件能夠合并指定的內容,比如spring.schema等等

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>3.2.0</version>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                    <configuration>
                        <transformers>
                            <transformer
                                    implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                <resource>META-INF/spring.handlers</resource>
                            </transformer>
                            <transformer
                                    implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                <resource>META-INF/spring.schemas</resource>
                            </transformer>
                            <transformer
                                    implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                <mainClass></mainClass>
                            </transformer>
                        </transformers>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

7.在其他項目中使用

在一個web項目中使用這個類

<?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:user="http://www.wuxueyou.cn/schema/user"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.wuxueyou.cn/schema/user http://www.wuxueyou.cn/schema/user.xsd">
 
    <user:self-user id="user2" userId="12" name="aaa"/>
    <bean id="user1" class="com.xueyou.User">
        <property name="userId" value="33"/>
        <property name="name" value="xiaoming"/>
    </bean>
</beans>

在controller中進行測試

package com.example.demo.controller; 
import com.xueyou.User;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; 
import javax.annotation.Resource;
 
@RestController
@RequestMapping("/namespacetest")
public class NamespaceController {
 
    @Resource(name = "user2")
    private User user;
 
    @RequestMapping("/user")
    public User namespacetest() {
        return user;
    }
}

運行結果:

運行結果

最終,我們可以使用spring-namespace對bean進行配置了。這樣比<bean>標簽要好的多。

以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關文章

  • Java基礎之Comparable與Comparator概述

    Java基礎之Comparable與Comparator概述

    這篇文章主要介紹了Java基礎之Comparable與Comparator詳解,文中有非常詳細的代碼示例,對正在學習java基礎的小伙伴們有非常好的幫助,需要的朋友可以參考下
    2021-04-04
  • Spring Cloud OAuth2 實現(xiàn)用戶認證及單點登錄的示例代碼

    Spring Cloud OAuth2 實現(xiàn)用戶認證及單點登錄的示例代碼

    這篇文章主要介紹了Spring Cloud OAuth2 實現(xiàn)用戶認證及單點登錄的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-10-10
  • 詳解java模板和回調機制

    詳解java模板和回調機制

    這篇文章主要為大家詳細介紹了java模板和回調機制,學習java模板,感興趣的朋友可以參考一下
    2016-03-03
  • Java生成Echarts表圖的2種實現(xiàn)方案

    Java生成Echarts表圖的2種實現(xiàn)方案

    這篇文章主要給大家介紹了關于Java生成Echarts表圖的2種實現(xiàn)方案,ECharts是一款功能非常強大的JavaScript圖表庫,文中通過代碼實例介紹的非常詳細,需要的朋友可以參考下
    2023-09-09
  • Java中BigDecimal的基本運算(詳解)

    Java中BigDecimal的基本運算(詳解)

    下面小編就為大家?guī)硪黄狫ava中BigDecimal的基本運算(詳解)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-10-10
  • jetbrain?fleet對標vscode實際操作

    jetbrain?fleet對標vscode實際操作

    Gradle是一個基于Apache Ant和Apache Maven概念項目自動化構建開源工具,jetbrain家的fleet(已獲得預覽權限)直接對標vscode?,?fleet有望超過vscode嗎?今天我們實際操作下
    2021-12-12
  • Java純代碼實現(xiàn)導出pdf

    Java純代碼實現(xiàn)導出pdf

    在項目開發(fā)中,產品的需求越來越奇葩啦,開始文件下載都是下載為excel的,做著做著需求竟然變了,要求能導出pdf,所以本文就來用Java實現(xiàn)導出pdf功能吧
    2023-12-12
  • SpringBoot整合定時任務之實現(xiàn)Scheduled注解的過程(一個注解全解決)

    SpringBoot整合定時任務之實現(xiàn)Scheduled注解的過程(一個注解全解決)

    這篇文章主要介紹了SpringBoot整合定時任務之實現(xiàn)Scheduled注解的過程(一個注解全解決),本文通過使用場景分析給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-09-09
  • Spark調度架構原理詳解

    Spark調度架構原理詳解

    這篇文章主要介紹了Spark 調度架構原理詳解,具有一定借鑒價值,需要的朋友可以參考下。
    2017-12-12
  • 分析java并發(fā)中的wait notify notifyAll

    分析java并發(fā)中的wait notify notifyAll

    一個線程修改一個對象的值,而另一個線程則感知到了變化,然后進行相應的操作,這就是wait()、notify()和notifyAll()方法的本質。本文將詳細來介紹它們概念實現(xiàn)以及區(qū)別
    2021-06-06

最新評論