当前位置: 首页 > 后端技术 > Java

ImportBeanDefinitionRegistrar的作用

时间:2023-04-01 13:33:36 Java

简介如果你用过Spring,你就知道注入一个Bean是非常简单的!@ResourceCustomBean自定义Bean;大概是这样,你可以注入一个已经存在于容器中的Bean,但是前提是你把这个Bean添加到容器中,添加起来很简单,只要@Component等一些框架提供的注解即可,@Service等上课都可以!现在我们要自己写一个组件,我们要自己管理我们的组件,用我们自己的注解来管理我们自己的bean。这时候ImportBeanDefinitionRegistrar登场了!基本功step1我们还有一个Enable开头的启动注解,@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.TYPE)@Documented@Import(ImportCustomBeanDefinitionRegistrar.class)//结合@Import注解,参考这里其他Blogpublic@interfaceEnableCustomBean{}step2然后把这个注解释放到启动类中,一般都是看到大佬Enable这样的,这次自己开发一个!@SpringBootApplication@EnableCustomBean公共类BootApplication{publicstaticvoidmain(String[]args){SpringApplication.run(BootApplication.class,args);}}step3自定义另一个Bean,publicclassCustomBean{privateStringname;publicStringgetName(){返回名称;}publicvoidsetName(Stringname){this.name=name;}@OverridepublicStringtoString(){return"CustomBean{"+"name='"+name+'\''+'}';}}嗯,看起来一切都很完美,只要将类CustomBean注册到容器中就OK了!Step4如何在容器中添加CustomBean?虽然我们自己定义了类,但是它们仍然运行在Spring中,我们仍然需要Spring来帮助我们进行一些前期工作。ImportBeanDefinitionRegistrar接口就是在这里实现的,今天一角!registerBeanDefinitions方法将在Spring启动时运行!在博客@Import中进行了解释。publicclassImportCustomBeanDefinitionRegistrarimplementsImportBeanDefinitionRegistrar{@OverridepublicvoidregisterBeanDefinitions(AnnotationMetadataimportingClassMetadata,BeanDefinitionRegistryregistry){//到这里就很明白了,StringsimpleName=CustomBean.class.getName();RootBeanDefinitionrootBeanDefinition=newRootBeanDefinition();rootBeanDefinition.setBeanClass(CustomBean.class);MutablePropertyValuespropertyValues=newMutablePropertyValues();propertyValues.add("name","Savey");rootBeanDefinition.setPropertyValues(propertyValues);registry.registerBeanDefinition(simpleName,rootBeanDefinition);}}step5跑个测试看下吧@SpringBootTestpublicclassImportBeanDefinitionRegistrarTest{//只管注册即可,@ResourceCustomBeanbean;//@ResourceApplicationContextapplicationContext;@Testpublicvoidtest_register_custom_bean(){System.out.println(bean);}}如无意外,打印出CustomBean{name='Savey'},说明我们的CustomBean已经加载到容器中了!高级我们要求将某个包下的所有类都添加到容器中。此外,我还需要添加一个自定义注解。只有在这个包下添加的自定义注解才能添加到容器中!其实有了上面的基本功,实现下面的功能就容易多了!step1自定义一个注解@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.TYPE)@Documentedpublic@interfaceSavey{}step2给EnableCustomBean注解添加一个属性,@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.TYPE)@Documented@Import(ImportCustomBeanDefinitionRegistrar.class)public@interfaceEnableCustomBean{/***定义要扫描的包*/String[]basePackages()default{};}step3修改启动类,@SpringBootApplication@EnableCustomBean(basePackages={"com.boot.boot.savey"})publicclassBootApplication{publicstaticvoidmain(String[]args){SpringApplication.run(BootApplication.class,args);}}这里我传递了一个basePackages属性来指定包下的类添加到容器中即可!!step4创建com.boot.boot.savey目录,在该目录下创建一些自定义的Bean。注意:给类加上Savey注解!!@Savey@Getter@Setter@ToStringpublicclassMoney{}@Savey@Getter@Setter@ToStringpublicclassWork{}//这个类不会用Savey注解,我不要加入容器,不想玩游戏,只想工作!所以没有了!@Getter@Setter@ToStringpublicclassPlayGame{}step5ModifyImportCustomBeanDefinitionRegistrar@OverridepublicvoidregisterBeanDefinitions(AnnotationMetadataimportingClassMetadata,BeanDefinitionRegistryregistry){//获取EnableCustomBean注解的属性finalMapAttributes=importingClassMetadata.getAnclass());//获取包扫描ClassPathScanningCandidateComponentProviderpathScanningCandidateComponentProvider=newClassPathScanningCandidateComponentProvider(false);//添加过滤带有Savey这个注解的类pathScanningCandidateComponentProvider.addIncludeFilter(newAnnotationTypeFilter(Savey.class));LinkedHashSetcandidateComponents=newLinkedHashSet<>();对于(StringbasePackages:(String[])attributes.get("basePackages")){candidateComponents.addAll(pathScanningCandidateComponentProvider.findCandidateComponents(basePackages));}//注册Beanfor(BeanDefinitioncandidateComponent:candidateComponents){registry.registerBeanDefinition(candidateComponent.getBeanClassName(),candidateComponent);}}进行测试@SpringBootTestpublicclassImportCustomScanPackagesDefinitionRegisterTest{@ResourceApplicationContextArlictestsapplicationContext;@Test复制.stream(applicationContext.getBeanDefinitionNames()).forEach(System.out::println);}}最后只有他们两个加入了容器,但是PlayGame没有!com.boot.boot.savey.Moneycom.boot.boot.savey.Work代码在GitHub上