【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)用上面的测试类再次验证,同样可以
你投入得越多,就能得到越多得价值