国产成年女人特黄特色毛片免_日本亚洲国产中文一区二区三区_国产精品福利一区_亚洲MA无码免费观看_欧美日韩一卡2卡三卡4卡乱码视频

快訊 >

世界觀天下!【Spring源碼】- 07 擴(kuò)展點(diǎn)之自定義標(biāo)簽

時(shí)間:2023-03-29 09:30:05       來(lái)源:騰訊云

Spring中正逐漸采用注解方式取代XML配置方式,所以,使用XML配置的機(jī)會(huì)正越來(lái)越少。然后,如果你開(kāi)發(fā)的工具模塊可能會(huì)被很多系統(tǒng)使用,考慮到兼容性問(wèn)題,就需要提供XML方式集成,這時(shí)就需要自定義標(biāo)簽;還有,你在看一些開(kāi)源源碼時(shí),一般也是提供自定義標(biāo)簽方式集成。所以,還是可以去了解一下自定義標(biāo)簽實(shí)現(xiàn)。

Spring中使用自定義標(biāo)簽還是比較簡(jiǎn)單,下面我們就實(shí)現(xiàn)一個(gè)自定義標(biāo)簽,其功能類似標(biāo)簽:將指定包路徑下帶有指定注解的Bean掃描注冊(cè)。


【資料圖】

1、首先,在resources/META-INF目錄下定義一個(gè)xsd文件,描述自定義標(biāo)簽屬性:

                                                                                

2、自定義NamespaceHandler,注冊(cè)使用CustomScannerBeanDefinitionParser解析器進(jìn)行處理:

public class ScannerNameSpaceHandler extends NamespaceHandlerSupport { @Override public void init() {  registerBeanDefinitionParser("scan", new CustomScannerBeanDefinitionParser()); }}

3、自定義CustomScannerBeanDefinitionParser解析器:

public class CustomScannerBeanDefinitionParser extends AbstractBeanDefinitionParser { @Override protected AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {  BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(CustomScannerConfigurer.class);  ClassLoader classLoader = ClassUtils.getDefaultClassLoader();  try {   String annotationClassName = element.getAttribute("annotation");   if (StringUtils.hasText(annotationClassName)) {    Class annotationClass = (Class) classLoader      .loadClass(annotationClassName);    builder.addPropertyValue("annotationClass", annotationClass);   }  } catch (Exception ex) {   XmlReaderContext readerContext = parserContext.getReaderContext();   readerContext.error(ex.getMessage(), readerContext.extractSource(element), ex.getCause());  }  builder.addPropertyValue("basePackage", element.getAttribute("base-package"));  return builder.getBeanDefinition(); }}

parseInternal()方法解析標(biāo)簽,然后生成一個(gè)BeanDefinitionSpring會(huì)自動(dòng)將其注冊(cè)到IoC容器中。如果標(biāo)簽只會(huì)注冊(cè)單個(gè)Bean,這里是需要返回注冊(cè)Bean對(duì)應(yīng)的BeanDefinition即可;如果是多個(gè)情況,這里一般是注冊(cè)一個(gè)配置類,將標(biāo)簽配置的屬性注入到配置類中,然后由配置類統(tǒng)一處理。

4、自定義CustomScannerConfigurer配置類:

public class CustomScannerConfigurer  implements BeanDefinitionRegistryPostProcessor, InitializingBean { private String basePackage; private Class annotationClass; @Override public void afterPropertiesSet() throws Exception {  //參數(shù)校驗(yàn)  notNull(this.basePackage, "Property "basePackage" is required"); } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { } @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {  ClassPathBeanDefinitionScanner scanner =    new ClassPathBeanDefinitionScanner(registry, false);  scanner.addIncludeFilter(new AnnotationTypeFilter(annotationClass));  scanner.setIncludeAnnotationConfig(false);  int beanCount = scanner.scan(basePackage);  registry.getBeanDefinitionNames(); } public String getBasePackage() {  return basePackage; } public void setBasePackage(String basePackage) {  this.basePackage = basePackage; } public Class getAnnotationClass() {  return annotationClass; } public void setAnnotationClass(Class annotationClass) {  this.annotationClass = annotationClass; }}

CustomScannerConfigurer實(shí)現(xiàn)了BeanDefinitionRegistryPostProcessor, InitializingBean兩個(gè)接口,之前分析過(guò)這兩個(gè)接口。重點(diǎn)在BeanDefinitionRegistryPostProcessor這個(gè)接口,其是一個(gè)BeanFactoryPostProcessor類型擴(kuò)展,可以向IoC容器注冊(cè)BeanDefinition。在postProcessBeanDefinitionRegistry()方法中創(chuàng)建一個(gè)ClassPathBeanDefinitionScanner對(duì)象,并將標(biāo)簽中配置設(shè)置進(jìn)去,即可實(shí)現(xiàn)掃描指定包路徑下帶有指定注解的Bean。

5、xsd是標(biāo)簽描述文件,NamespaceHandler則是標(biāo)簽后臺(tái)處理邏輯入口,現(xiàn)在需要將兩者進(jìn)行關(guān)聯(lián),在resources/META-INF目錄下創(chuàng)建兩個(gè)文件:Spring.schemasSpring.handlers,分別指定xsd文件位置和NamespaceHandler位置,這樣就實(shí)現(xiàn)了標(biāo)簽和后臺(tái)邏輯關(guān)聯(lián),其內(nèi)容見(jiàn)下:

Spring.schemashttp\://www.simon.org/schema/scan.xsd=META-INF/custom-scan.xsd
Spring.handlershttp\://www.simon.org/schema/scan=customschema.demo03.ScannerNameSpaceHandler

自定義標(biāo)簽描述以及對(duì)于的后臺(tái)處理邏輯都配置完成,下面我們就開(kāi)始進(jìn)行測(cè)試。

1、首先,定義個(gè)注解,用于在掃描Bean時(shí)過(guò)濾使用:

@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Indexedpublic @interface MyComponent { String value() default "";}

2、在customschema.demo03.bean包路徑下定義三個(gè)類:TestService01、TestService02TestService03,將后面兩個(gè)類使用@MyComponent注解標(biāo)注下;

3、編寫SpringXml配置文件,這里就可以使用我們剛才自定義的標(biāo)簽:

 

4、測(cè)試用例:

@Testpublic void test01() { ApplicationContext context = new ClassPathXmlApplicationContext("custom-schema.xml"); Arrays.stream(context.getBeanDefinitionNames()).forEach(System.out::println);}

從輸出結(jié)果就可以看到,TestService01由于沒(méi)有帶有@MyComponent注解,所以沒(méi)有注冊(cè),TestService02TestService03都會(huì)被注冊(cè)到容器中。

關(guān)鍵詞:

首頁(yè)
頻道
底部
頂部
閱讀下一篇