zoukankan      html  css  js  c++  java
  • 聊聊自定义实现的SPI如何与spring进行整合

    前言

    上一篇文章主要聊聊如何实现一个带有拦截器功能的SPI。今天就来聊聊自定义的SPI如何与spring整合。

    思考:我们实现的SPI要整合spring哪些东西?或者我们要利用spring的哪些特性实现我们哪些东西?

    spring除了被大家熟知的IOC和AOP之外,还有它也提供了很丰富的扩展点,比如各种后置处理器,今天我们就聊聊大家相对熟悉的话题,如何通过自定义注解把SPI注入到spring容器中

    整合思路

    1、自定义注解

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

    2、自定义bean定义扫描器

    public class ActivateClassPathBeanDefinitionScanner extends ClassPathBeanDefinitionScanner {
    
    
        public ActivateClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry) {
            super(registry);
        }
    
    
        @SneakyThrows
        @Override
        protected void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) {
            super.registerBeanDefinition(definitionHolder, registry);
            Class clz = Class.forName(definitionHolder.getBeanDefinition().getBeanClassName());
            Activate activate = AnnotationUtils.findAnnotation(clz,Activate.class);
            if(ObjectUtils.isNotEmpty(activate) && StringUtils.isNotBlank(activate.value())){
                String activateName = getEnvironment().resolvePlaceholders(activate.value());
                registry.registerBeanDefinition(activateName,definitionHolder.getBeanDefinition());
            }
        }
    
        @Override
        protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
            return super.isCandidateComponent(beanDefinition) && beanDefinition.getMetadata()
                    .hasAnnotation(Activate.class.getName());
        }
    

    3、定义ImportBeanDefinitionRegistrar

    public class SpiRegister implements ImportBeanDefinitionRegistrar, EnvironmentAware {
    
        private Environment environment;
    
    
        @Override
        public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
            Set<String> basePackages = this.getBasePackages(importingClassMetadata);
            String[] packages = {};
            SpiBeanUtils.registerActivateInstances(registry,environment,basePackages.toArray(packages));
        }
    

    4、自定义enabled注解

    @Target(value = ElementType.TYPE)
    @Retention(value = RetentionPolicy.RUNTIME)
    @Documented
    @Import(SpiRegister.class)
    public @interface EnableSpi {
    
      
        String[] value() default {};
    
     
        String[] basePackages() default {};
    
      
        Class<?>[] basePackageClasses() default {};
    }
    

    示例演示

    1、在需要注入到spring容器的类上加上@Activate注解

    @Activate("hello-mysql")
    public class SpringMysqlDialect implements SpringSqlDialect {
    
        @Autowired
        private MysqlDialectService mysqlDialectService;
    
        @Override
        public String dialect() {
            return mysqlDialectService.dialect();
        }
    
    
    }
    

    2、启动类上加上扫描SPI范围注解

    @SpringBootApplication(scanBasePackages = "com.github.lybgeek")
    @EnableSpi(basePackages = "com.github.lybgeek")
    public class SpiTestApplication implements ApplicationRunner 
    

    3、利用getBeansOfType进行验证

     applicationContext.getBeansOfType(SpringSqlDialect.class)
                    .forEach((beanName,bean) -> System.out.println(beanName + "-->" + bean));
    

    打印结果如下

    hello-mysql-->com.github.lybgeek.dialect.mysql.SpringMysqlDialect@433348bc
    

    说明已经注入到spring容器中

    总结

    把项目的服务托管给spring ioc容器,可以算是与spring整合比较基础的动作,本文演示也是相对基础的一环,spring 强大的地方,在于它的扩展性,在spring bean的生命周期中,基本上随处可见扩展点,感兴趣的朋友后续可以自行体会验证

    demo链接

    https://github.com/lyb-geek/springboot-learning/tree/master/springboot-spi-enhance/springboot-spi-framework-spring

  • 相关阅读:
    网页版游戏(俄罗斯方块)
    模拟简单进程调度实验
    从小型网站到超大规模网站的MySQL参考架构
    Google Chart Tools学习笔记 二 Area Chart
    大话设计模式——建造者模式
    内存管理:分页,分段,段页结合
    2012第50周星期一自制力网摘
    第49周星期五糟糕破系统
    2012年第50周四
    2012第50周五
  • 原文地址:https://www.cnblogs.com/linyb-geek/p/15520349.html
Copyright © 2011-2022 走看看