簡介
- ImportBeanDefinitionRegistrar類只能通過其他類@Import的方式來加載,通常是啓動類或配置類。
- 使用@Import,如果括號中的類是ImportBeanDefinitionRegistrar的實現類,則會調用接口方法,將其中要註冊的類註冊成bean。
- 實現該接口的類擁有註冊bean的能力。
手動把一個類註冊成bean
-
首先寫一個類,最終要把它註冊爲bean。
public class HelloService { }
自定義ImportBeanDefinitionRegistrar實現類手動註冊bean。
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); } }
最後定義一個配置類發現一下上面的ImportBeanDefinitionRegistrar實現類。
@Configuration @ComponentScan("com.haien.import2.domain") @Import(HelloImportBeanDefinitionRegistrar.class) public class HelloConfiguration { }
測試:
@RunWith(SpringRunner.class) @SpringBootTest @ContextConfiguration(classes = {HelloConfiguration.class}) //表示只需要這一個文件 public class DemoApplicationTest2 { @Resource HelloService helloService; @Test public void contextLoads(){ System.out.println(helloService.getClass()); } }
自己寫一個註解實現@Component的功能
-
目標:自己寫一個註解@Mapper,配合其他類,實現被註解類可以被註冊成bean的功能。
@Mapper:
@Documented @Inherited @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE,ElementType.FIELD,ElementType.METHOD,ElementType.PARAMETER}) public @interface Mapper { }
註釋於類上:
@Mapper public class CountryMapper { }
實現ImportBeanDefinitionRegistrar接口,重寫registerBeanDefinitions方法,手動註冊bean;同時實現一些Aware接口,以便獲取Spring的一些數據。
public class MapperAutoConfiguredMyBatisRegistrar implements ImportBeanDefinitionRegistrar,ResourceLoaderAware,BeanFactoryAware { private ResourceLoader resourceLoader; private BeanFactory beanFactory; @Override public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry registry) { MyClasssPathBeanDefinitionScanner scanner= new MyClasssPathBeanDefinitionScanner(registry,false); scanner.setResourceLoader(resourceLoader); scanner.registerFilters(); scanner.doScan("com.haien.import1.domain"); } @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { this.beanFactory=beanFactory; } @Override public void setResourceLoader(ResourceLoader resourceLoader) { this.resourceLoader=resourceLoader; } }
以上我們還藉助了掃描器ClassPathBeanDefinitionScanner,通過它來獲取我們需要註冊的bean。
public class MyClasssPathBeanDefinitionScanner extends ClassPathBeanDefinitionScanner { public MyClasssPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters) { super(registry, useDefaultFilters); } protected void registerFilters(){ addIncludeFilter(new AnnotationTypeFilter(Mapper.class)); } @Override protected Set<BeanDefinitionHolder> doScan(String... basePackages) { return super.doScan(basePackages); } }
測試:
@RunWith(SpringRunner.class) @SpringBootTest(classes = MapperAutoConfig.class) //只將MapperAutoConfig類納入測試環境的Spring容器中, //或@ContextConfiguration(classes = {MapperAutoConfig.class}) public class DemoApplicationTest { @Resource CountryMapper countryMapper; @Test public void contextLoads(){ System.out.println(countryMapper.getClass()); } }