【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)用上面的测试类再次验证,同样可以

 

posted @ 2019-12-13 21:07  N!CE波  阅读(1849)  评论(0编辑  收藏  举报