在Spring IOC 注解 — @Bean,@Scope 和 @Lazy 一篇,我们介绍了使用@Bean注解将一个组件交给Spring IOC容器去管理,除此之外我们还可以通过@ImportResource和@Import往容器中注入Bean。
@ImportResource
@ImportResource用于导入包含Bean定义的资源,一般为我们早期学习Spring时配置的xml资源文件,它有三个属性:
- value 要导入的资源的位置,同locations属性一致。
- locations 要导入的资源的位置,同value属性一致。
- reader,要导入的资源 BeanDefinitionReader示例。
如下代码为导入classpath下的bean.xml代码示例,它与@Configuration注解一起使用,表示是一个配置类.
@Configuration
@ImportResource(locations={"classpath:bean.xml"})
public class ImportResourceConfiguration {
}
@Import
@ImportResource注解一般使用xml配置配置Bean文件,而@Import可以导入某个类或者按照某些规则去往Spring IOC容器注册Bean。如下代码所示,我们将ImportBean组件注册到Spring IOC中,可以通过context.getBean(ImportBean.class)方法获取到改类的实例
@Configuration
@Import({ImportBean.class})
public class ImportConfiguration {
}
除此了上面的用法之外,我们还可以实现org.springframework.context.annotation.Import.Selector接口,实现该接口的selectImports方法,该方法返回一个包含全类名的String数组,可以向Spring中批量注册Bean
public class CustomizedImportSelector implements ImportSelector {
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[] {"cn.org.microservice.spring.ioc.impor.ImportBean"};
}
}
@Configuration
@Import({CustomizedImportSelector.class})
public class ImportConfiguration {
}
我们还可以实现ImportBeanDefinitionRegistrar用于动态注册Bean。ImportBeanDefinitionRegistrar的功能比Selector更强大,Selector只能注册知道全类名的类,ImportBeanDefinitionRegistrar则可以根据类型或者类上的注解注册Bean。如下代码我们实现ImportBeanDefinitionRegistrar。
public class CustomizedImportBeanRegister implements ImportBeanDefinitionRegistrar {
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClass(ImportBean.class);
registry.registerBeanDefinition("importBean", beanDefinition);
String [] packages = (String[]) importingClassMetadata.getAnnotationAttributes(ComponentScan.class.getName()).get("value");
ClassPathBeanDefinitionScanner provider = new ClassPathBeanDefinitionScanner(registry, false);
TypeFilter typeFilter = new AnnotationTypeFilter(Mapper.class);
provider.addIncludeFilter(typeFilter);
provider.scan(packages);
}
}
上面代码中ClassPathBeanDefinitionScanner继承了ClassPathScanningCandidateComponentProvider类,ClassPathScanningCandidateComponentProvider中有两个TypeFilter集合,includeFilters、excludeFilters。满足任意includeFilters会被加载,同样的满足任意excludeFilters不会被加载。