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