Preface
Before we talked about custom SPI integrates with spring , today we will talk about how to inject spi objects into the spring container through a custom label
Realization routine
1. Custom xsd
example :
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:tool="http://www.springframework.org/schema/tool"
xmlns="http://lybgeek.github.com/schema/spi"
targetNamespace="http://lybgeek.github.com/schema/spi">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace"/>
<xsd:import namespace="http://www.springframework.org/schema/beans"
schemaLocation="http://www.springframework.org/schema/beans/spring-beans.xsd"/>
<xsd:import namespace="http://www.springframework.org/schema/tool"/>
<xsd:annotation>
<xsd:documentation>
<![CDATA[ Namespace support for spi services ]]></xsd:documentation>
</xsd:annotation>
<xsd:complexType name="scanType">
<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="basePackages" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation><![CDATA[ Specify the spi package name to scan, multiple scan packages are separated by commas ]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
<xsd:complexType name="interceptorType">
<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="class" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation><![CDATA[ Interceptor class name]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
<xsd:complexType name="interceptorChainType">
<xsd:choice>
<xsd:element ref="interceptor" minOccurs="1" maxOccurs="unbounded"/>
</xsd:choice>
</xsd:complexType>
<xsd:element name="scan" type="scanType">
<xsd:annotation>
<xsd:documentation><![CDATA[ The scan config ]]></xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="interceptor" type="interceptorType">
<xsd:annotation>
<xsd:documentation><![CDATA[ The interceptor config ]]></xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="interceptorChain" type="interceptorChainType">
<xsd:annotation>
<xsd:documentation><![CDATA[ The interceptorChainType config ]]></xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:schema>
ps: If you are not familiar with xsd, you can refer to the following link
https://www.w3school.com.cn/schema/index.asp
2. Custom parse the BeanDefinitionParser parser
example:
public class AnnotationBeanDefinitionParser implements BeanDefinitionParser {
private final Class<?> beanClass;
public AnnotationBeanDefinitionParser(Class<?> beanClass) {
this.beanClass = beanClass;
}
@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
String packageToScan = element.getAttribute("basePackages");
String[] packagesToScan = trimArrayElements(commaDelimitedListToStringArray(packageToScan));
RootBeanDefinition beanDefinition = new RootBeanDefinition();
beanDefinition.setBeanClass(beanClass);
beanDefinition.setLazyInit(false);
beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue(0,packagesToScan);
String beanName = BeanUtils.generateBeanName(element,"id",parserContext,beanClass.getName());
parserContext.getRegistry().registerBeanDefinition(beanName,beanDefinition);
return beanDefinition;
}
}
3. Define the NamespaceHandler implementation class to handle custom label handlers
example:
public class SpiNamespaceHandler extends NamespaceHandlerSupport {
@Override
public void init() {
registerBeanDefinitionParser("scan", new AnnotationBeanDefinitionParser(SpiAnnotationPostProcessor.class));
}
}
4. Write the location of the processor and label to spring.handlers and spring.schemas
example:
spring.handlers
http\://lybgeek.github.com/schema/spi=com.github.lybgeek.spring.schema.SpiNamespaceHandler
spring.schemas
http\://lybgeek.github.com/schema/spi/spi.xsd=META-INF/spi/spi.xsd
Note: spring.handlers, spring.schemas need to be placed under the resource/META-INF directory
Sample demo
1. Configure xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:spi="http://lybgeek.github.com/schema/spi"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://lybgeek.github.com/schema/spi http://lybgeek.github.com/schema/spi/spi.xsd">
<spi:scan basePackages="com.github.lybgeek"></spi:scan>
2. Import xml on the startup class
@SpringBootApplication
@ImportResource(locations = "classpath:/spi.xml")
public class SpiTestXmlApplication {
public static void main(String[] args) throws Exception{
SpringApplication.run(SpiTestXmlApplication.class);
}
}
3. Verify whether the SPI is injected into the spring container
@Override
public void run(ApplicationArguments args) throws Exception {
applicationContext.getBeansOfType(SpringSqlDialect.class)
.forEach((beanName,bean) -> System.out.println(beanName + "-->" + bean));
}
The console input is as follows
springMysqlDialect-->com.github.lybgeek.dialect.mysql.SpringMysqlDialect@73041b7d
mysql-hello-->com.github.lybgeek.dialect.mysql.SpringMysqlDialect@574059d5
springOracleDialect-->com.github.lybgeek.dialect.oracle.SpringOracleDialect@4a50d04a
Description has been imported into the spring container
Summarize
Since the introduction of annotation drivers in spring 3+, xml is rarely used in new projects, but if it is an old project, if you want to inject custom tags into spring, you can use the method in this article.
The routine is as follows
- 1. Custom xsd
- 2. Custom parse the BeanDefinitionParser parser
- 3. Define the NamespaceHandler implementation class to handle custom label handlers
- 4. Write the location of the processor and label to spring.handlers and spring.schemas
The implementation of this article is relatively simple. If you want to use it in depth, I recommend looking at the dubbo custom spring tag.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。