菜々鳥はあなたを連れてspringラベルを広げて、カスタムbeanを実現します.

39902 ワード

拡張スプリングラベル
いくつかのシーンではspringタグを拡張する必要があります.springは私達のカスタマイズしたラベルを識別できます.カスタマイズしたbeanを実現します.例えば、dubboでdubbo:serviceを定義するなど、shardingsphereはspringに適合し、springプロファイルでライブラリ分割ポリシーを定義するなど、今日は主にspringカスタムラベルを拡張し、demoを実現する方法を分析します.後に自己研削分庫を表の中間部品に分けてspring配置を実現するために下敷きをする.
まずは以下の情報を簡単に知る必要があります.
xsdとDMD
  • XML SchemaはXMLに基づくDMDの代替である.
  • XML SchemaはXML文書の構造を記述する.
  • XML Schema言語はXML Schema定義(XML Schema Definition、XSD)とも呼ばれています.
  • XML SchemaはDMDよりも強いです.
  • XSD-元素
    元素はXML Schema毎のルート要素です.
    
    
    <xs:schema>
    
    ...
    ...
    
    xs:schema>
    
    要素には属性が含まれます.schema声明はしばしばこのように見える.
    
     
    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
    targetNamespace="http://www.w3school.com.cn"
    xmlns="http://www.w3school.com.cn"
    elementFormDefault="qualified">
    
    ...
    ...
    xs:schema>
    
    コードの説明:
    次の断片:
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    
    schemaで使用される要素とデータのタイプを表示します.名前空間から来ました.http://www.w3.org/2001/XMLSchema」をクリックします.名前空間からも規定されています.http://www.w3.org/2001/XMLSchema」要素およびデータタイプは、プレフィックスxsを使用するべきである.
    この定型表現:
    targetNamespace="http://www.w3school.com.cn" 
    
    このschemaで定義された要素(note,to,from,heading,body)を表示します.名前空間から来ます.http://www.w3school.com.cn」をクリックします
    この定型表現:
    xmlns="http://www.w3school.com.cn" 
    
    デフォルトの名前空間は「http://www.w3school.com.cn」をクリックします
    この定型表現:
    elementFormDefault="qualified" 
    
    任意のXMLのインスタンスドキュメントが使用され、このschemaで宣言された要素は名前空間によって定義されなければならないことを指摘する.
    スプリングIOC容器
    コントロールが反転したり依存が反転したり、オブジェクト間の引用や依存関係があります.スプリング容器によって完成され、IOC容器はbeanの管理が実現されました.だから、スプリングはどのようにbeanをロードしますか?及びビーンを容器に登録しますか?
    spring対beanの定義インターフェース
    public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement{}
    
    各beanはBenDefinitionを構築し、完成したら容器に登録します.実際にはspringメンテナンスのHashMapで、BenDefinitionをロードする方法を紹介します.
    BenDefinitionのロードと解析
    FileSystemXmlAppleicationComptextイニシャルエントリ
    public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
    			throws BeansException {
    
    		super(parent);
    		setConfigLocations(configLocations);
    		if (refresh) {
    			refresh();
    		}
    	}
    
    refresh方法はコンテナを起動して、beanをロードすることを含んで、つまりloadBenDefinitionsです.
    	@Override
    	protected final void refreshBeanFactory() throws BeansException {
    		if (hasBeanFactory()) {
    			destroyBeans();
    			closeBeanFactory();
    		}
    		try {
    			DefaultListableBeanFactory beanFactory = createBeanFactory();
    			beanFactory.setSerializationId(getId());
    			customizeBeanFactory(beanFactory);
    			loadBeanDefinitions(beanFactory);
    			synchronized (this.beanFactoryMonitor) {
    				this.beanFactory = beanFactory;
    			}
    		}
    		catch (IOException ex) {
    			throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
    		}
    	}
    
    
    loadBenDefinitions法で直接解析xmlを使わずに、beanDefinitionを構築し、対応するreaderを通じて取得し、結合の役割を果たします.
    protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
    		// Create a new XmlBeanDefinitionReader for the given BeanFactory.
    		XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
    
    		// Configure the bean definition reader with this context's
    		// resource loading environment.
    		beanDefinitionReader.setEnvironment(this.getEnvironment());
    		beanDefinitionReader.setResourceLoader(this);
    		beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
    
    		// Allow a subclass to provide custom initialization of the reader,
    		// then proceed with actually loading the bean definitions.
    		initBeanDefinitionReader(beanDefinitionReader);
    		loadBeanDefinitions(beanDefinitionReader);
    	}
    
    
    すべてのリソースローディングを取得します.例えば、プロジェクトに複数のxmlファイルが存在する可能性があります.
    protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
    		Resource[] configResources = getConfigResources();
    		if (configResources != null) {
    			reader.loadBeanDefinitions(configResources);
    		}
    		String[] configLocations = getConfigLocations();
    		if (configLocations != null) {
    			reader.loadBeanDefinitions(configLocations);
    		}
    	}
    
    
    beanを読み込み、beanの総数を返します.
    	public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {
    		Assert.notNull(locations, "Location array must not be null");
    		int counter = 0;
    		for (String location : locations) {
    			counter += loadBeanDefinitions(location);
    		}
    		return counter;
    	}
    
    	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;
    	}
    
    BeanDefinitionParter Delegateにおいて、beanDefinitionの解析が完了しました.
    	public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
    		String namespaceUri = getNamespaceURI(ele);
    		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));
    	}
    
    上のコードでは、解析xmlはhandler処理に対応するインターフェースNamespace Handlerであり、このhandlerは拡張可能であり、後はこの拡張springタグに基づいて、bean登録を実現し、PropertyValuesによってBenDefinitionに属性を設定することができます.
    public interface PropertyValues {
        PropertyValue[] getPropertyValues();
    
        PropertyValue getPropertyValue(String var1);
    
        PropertyValues changesSince(PropertyValues var1);
    
        boolean contains(String var1);
    
        boolean isEmpty();
    }
    
    以上の原理を理解して、次にspring拡張ラベルを実現するのは比較的に容易です.
    拡張スプリングラベル実現
    カスタムラベルを実現
    spring登録beanの形式は以下の通りです.
     <bean class="com.stu.code.aspect.AcctService">bean>
    
    ここではビーンと似たような注釈を実現し、自動的にタイブルConfigに属性を注入します.ここでは原理を紹介し、簡単なデモを持っています.
    <table name="acct" type="sharding" />
    
    1、Table Configを定義する
    /**
     * @author Qi.qingshan
     * @date 2020/5/2
     */
    public class TableConfig {
    
        private String name;
    
        private String type;
    
       //  get set  
    }
    
    
    /**
     * @author Qi.qingshan
     * @date 2020/5/3
     */
    public class ShardingConfiguration {
    
        private TableConfig tableConfig;
    
        public TableConfig getTableConfig() {
            return tableConfig;
        }
    
        public void setTableConfig(TableConfig tableConfig) {
            this.tableConfig = tableConfig;
        }
    }
    
    
    2.XML schemaファイルを作成する、つまり.xsdファイルは、xmlファイルに対する記述であり、ファイルの位置はカスタマイズできます.
    
    
    <xsd:schema xmlns="http://code.stu.com/schema/sharding"
                xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                xmlns:beans="http://www.springframework.org/schema/beans"
                targetNamespace="http://code.stu.com/schema/sharding"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
        <xsd:element name="table">
            <xsd:complexType>
                <xsd:attribute name="name" type="xsd:string" use="required"/>
                <xsd:attribute name="type" type="xsd:string"/>
            xsd:complexType>
        xsd:element>
    
    xsd:schema>
    
    その中の注意、後の登録は使います.
    xmlns="http://code.stu.com/schema/sharding
    
    3、Namespace Handlerを実現する
    Namespace Handler Supportを継承すればいいです.handlerにパーパーを登録します.
    /**
     * @author Qi.qingshan
     * @date 2020/5/2
     */
    public class TableNamespaceHandler extends NamespaceHandlerSupport {
        public void init() {
        	/** table xsd    element*/
            registerBeanDefinitionParser("table", new TableBeanDefinitonParser());
        }
    }
    
    4、BeanDefinitionParsserを実現する
    パーサーでビーンDefinitionの構築を完了し、容器に登録する.
    /**
     * @author Qi.qingshan
     * @date 2020/5/2
     */
    public class TableBeanDefinitonParser implements BeanDefinitionParser {
    
        public BeanDefinition parse(Element element, ParserContext parserContext) {
            AbstractBeanDefinition definition = SpringBeanExtension.getBeanDefinitionByElement(element);
            parserContext.getRegistry().registerBeanDefinition("shardingConfiguration", definition);
            return definition;
        }
    }
    
    
    public final class SpringBeanExtension {
    
        public static AbstractBeanDefinition getBeanDefinitionByElement(Element element) {
            BeanDefinitionBuilder factory = BeanDefinitionBuilder.rootBeanDefinition(ShardingConfiguration.class);
           //ShardingConfiguration   tableConfig  ,   set   
            factory.addPropertyValue("tableConfig", parseTableDefinine(element));
            return factory.getBeanDefinition();
        }
    
        private static BeanDefinition parseTableDefinine(Element element) {
            BeanDefinitionBuilder factory = BeanDefinitionBuilder.rootBeanDefinition(TableConfig.class);
           //    
            factory.addPropertyValue("name", element.getAttribute("name"));
            factory.addPropertyValue("type", element.getAttribute("type"));
            return factory.getBeanDefinition();
        }
    }
    
    
    5、HandlerとXML schemaを登録する
    META-INFの下にspring.handlesとspings.schemasファイルを新築しました.内容は以下の通りです.
    http\://code.stu.com/schema/sharding=com.stu.spring.handler.TableNamespaceHandler
    
    http\://code.stu.com/schema/sharding/spring-table.xsd=META-INF/spring-table.xsd
    
    6、springファイルにxsdを導入する
    
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:sharding="http://code.stu.com/schema/sharding"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd
           http://code.stu.com/schema/sharding
           http://code.stu.com/schema/sharding/spring-table.xsd">
    
        <sharding:table name="acct" type="global">sharding:table>
    
    beans>
    
    シーン検証
    xmlを例にとって、Class PathXml Apple Controtextでspringプロファイルをロードします.
      @Test
        public void testSringExtension(){
            ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
            ShardingConfiguration shardingConfiguration = context.getBean(ShardingConfiguration.class);
            System.out.println(shardingConfiguration.getTableConfig().getName());
    
        }
    
    この文章はspringラベルを拡張し、ユーザー定義のbeanプロセスを実現するために紹介しました.章節のspring IOC容器によってspringの実現を分析したり、dubboやshardgsphereのソースコードを勉強したりします.