【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)用上面的測試類再次驗證,同樣可以

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM