• 【Spring Boot】Spring Boot之使用ImportBeanDefinitionRegistrar类实现动态注册Bean


    一、ImportBeanDefinitionRegistrar类介绍

      ImportBeanDefinitionRegistrar类通过其他@Configuration类通过@Import的方式来加载,通常是启动类或配置类。
      然后会调用该接口方法,将其中要注册的类注册成bean。
      通过实现该接口的类拥有注册bean的能力。
      可以实现遗下Aware接口
        EnvironmentAware
        BeanFactoryAware
        BeanClassLoaderAware
        ResourceLoaderAware

    二、实现注册指定类型的Bean

    1)定义一个需要用来注册的service类

    /**
     * @author zhangboqing
     * @date 2019/12/13
     */
    @Slf4j
    public class HelloService {
        public void sayHello() {
          log.info("Hello!!!");
        }
    }

    2)定义HelloImportBeanDefinitionRegistrar类实现ImportBeanDefinitionRegistrar接口

    /**
     * @author zhangboqing
     * @date 2019/12/13
     */
    public class HelloImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    
        @Override
        public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
            // 扫描注解
            Map<String, Object> annotationAttributes = importingClassMetadata.getAnnotationAttributes(ComponentScan.class.getName());
            String[] basePackages = (String[]) annotationAttributes.get("basePackages");
    
            // 扫描类
            ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(registry, false);
            // 指定类
            TypeFilter helloServiceFilter = new AssignableTypeFilter(HelloService.class);
            scanner.addIncludeFilter(helloServiceFilter);
            scanner.scan(basePackages);
        }
    }

    3)定义HelloConfiguration配置类,引入ImportBeanDefinitionRegistrar

    /**
     * @author zhangboqing
     * @date 2019/12/13
     */
    @Configuration
    @ComponentScan("com.zbq.springbootdemo.speciality.dynamicRegisterBean.ImportBeanDefinitionRegistrar")
    @Import(HelloImportBeanDefinitionRegistrar.class)
    public class HelloConfiguration {
    }

    4)定义测试类可验证HelloService类是否注册成功

    /**
     * @author zhangboqing
     * @date 2019/12/13
     */
    @SpringBootTest(classes = {HelloConfiguration.class})
    // 指定配置类
    //@ContextConfiguration(classes = {HelloConfiguration.class})
    public class HelloImportBeanDefinitionRegistrarTest {
    
        @Autowired
        private HelloService helloService;
    
        @Test
        public void testHelloService() {
            helloService.sayHello();
        }
    }

    三、实现注册指定注解的Bean

    1)自定义注解HelloAnnotation

    /**
     * @author zhangboqing
     * @date 2019/12/13
     */
    @Documented
    @Inherited
    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.TYPE})
    public @interface HelloAnnotation {
    }

    2)将注解加入到HelloService类上

    /**
     * @author zhangboqing
     * @date 2019/12/13
     */
    @Slf4j
    @HelloAnnotation
    public class HelloService {
        public void sayHello() {
          log.info("Hello!!!");
        }
    }

    3)修改HelloImportBeanDefinitionRegistrar类,将类型过滤器从指定类型变为指定注解

    /**
     * @author zhangboqing
     * @date 2019/12/13
     */
    public class HelloImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    
        @Override
        public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
            // 扫描注解
            Map<String, Object> annotationAttributes = importingClassMetadata.getAnnotationAttributes(ComponentScan.class.getName());
            String[] basePackages = (String[]) annotationAttributes.get("basePackages");
    
            // 扫描类
            ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(registry, false);
            // 指定类
    //        TypeFilter helloServiceFilter = new AssignableTypeFilter(HelloService.class);
            // 指定注解
            TypeFilter helloServiceFilter = new AnnotationTypeFilter(HelloAnnotation.class);
            scanner.addIncludeFilter(helloServiceFilter);
            scanner.scan(basePackages);
        }
    }

    4)用上面的测试类再次验证,同样可以

  • 相关阅读:
    ffmpeg.c函数结构简单分析(画图)
    FFMPEG之协议(文件)操作----AVIOContext, URLContext, URLProtocol
    FFmpeg源代码结构图
    解密FFmpeg播放状态控制内幕
    转 A10/A20 Bootloader加载过程分析
    [置顶] 编译linux内核时出现"mkimage" command not found
    Thumb指令集与ARM指令集的区别
    gsoap创建webservice服务简单教程
    ubuntu11.10(TQ210)下移植boa服务器
    500 Internal Error Wamp 服务器错误处理
  • 原文地址:https://www.cnblogs.com/756623607-zhang/p/12037291.html
Copyright © 2020-2023  润新知