SpringBoot之@Import详解
前言
SpringBoot 的 @Import 用于选择性地将指定的类实例注入之Spring IOC容器中。一般使用场景:针对依赖包,选择性地将一些类加载到当前容器,或者根据一些具体场景选择性的加载一些你想要的类到当前容器。
SpringBoot 提供了三种使用 @Import 将 类实例注入至 Spring IOC Container中 的实例。
- 直接注入
- 实现 ImportSelector 注入
- 实现 ImportBeanDefinitionRegistrar 接口注入
直接注入
- 购买服务
public class BuyService {
}
- 支付服务
public class PayService {
}
- 支付配置类(未加上@Configuration不会加载到spring容器)
public class PayConfiguation {
@Bean
public PayService payService() {
return new PayService();
}
}
通过@Import直接注入购买服务和支付服务,代码如下
@SpringBootApplication
@Import({BuyService.class, PayConfiguation.class})
public class ImportAnnotationApplication implements ApplicationRunner {
@Autowired
private ApplicationContext applicationContext;
public static void main(String[] args) {
SpringApplication.run(ImportAnnotationApplication.class, args);
}
}
实现 ImportSelector 注入
(1)场景:现在有两种上传方式:ceph和ftp,要求根据@open注解配置的上传方式,来加载对应的类。可以考虑使用ImportSelector。
两个服务:ceph服务与ftp服务
public class CephService {
}
public class FtpService {
}
importSelector的具体实现:根据@Open注解配置的开启的类型来加载对应的服务。
public class CustomImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
if (importingClassMetadata.hasAnnotation(Open.class.getName())) {
if ("ftp".equals(importingClassMetadata.getAnnotationAttributes(Open.class.getName()).get("value"))) {
return new String[] {"com.nestor.importannotation.service.FtpService"};
}
else {
return new String[] {"com.nestor.importannotation.service.CephService"};
}
}
return new String[]{};
}
@Override
public Predicate<String> getExclusionFilter() {
return null;
}
}
@Open注解如下:
@Target(ElementType.TYPE)
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Import(CustomImportSelector.class)
public @interface Open {
String value();
}
启动类配置
@SpringBootApplication
@Open("ftp")
public class ImportAnnotationApplication implements ApplicationRunner {
@Autowired
private ApplicationContext applicationContext;
public static void main(String[] args) {
SpringApplication.run(ImportAnnotationApplication.class, args);
}
}
(2)Spring注解@EnableTransactionManagement中使用了ImportSelector注入的方式,具体代码可以查看源码。
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import({TransactionManagementConfigurationSelector.class})
public @interface EnableTransactionManagement {
boolean proxyTargetClass() default false;
AdviceMode mode() default AdviceMode.PROXY;
int order() default 2147483647;
}
实现 ImportBeanDefinitionRegistrar 接口注入
(1)场景与上面类似不过多赘述。
public class CustomImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
if (!importingClassMetadata.hasAnnotation(Open.class.getName())) {
return;
}
Map<String, Object> annotationAttributes = importingClassMetadata.getAnnotationAttributes(Open.class.getName());
if ("ftp".equals(annotationAttributes.get("value"))) {
registry.registerBeanDefinition("ftpService",
BeanDefinitionBuilder.rootBeanDefinition(FtpService.class).getBeanDefinition());
return;
}
registry.registerBeanDefinition("cephService",
BeanDefinitionBuilder.rootBeanDefinition(CephService.class).getBeanDefinition());
}
}
启动类配置
@SpringBootApplication
@Open("ftp")
public class ImportAnnotationApplication implements ApplicationRunner {
@Autowired
private ApplicationContext applicationContext;
public static void main(String[] args) {
SpringApplication.run(ImportAnnotationApplication.class, args);
}
}
(2)你也可以参考Mybatis的@MapperScan
注解,使用的就是这种方式扫描注入。
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Import({MapperScannerRegistrar.class})
@Repeatable(MapperScans.class)
public @interface MapperScan {
String[] value() default {};
String[] basePackages() default {};
Class<?>[] basePackageClasses() default {};
Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;
Class<? extends Annotation> annotationClass() default Annotation.class;
Class<?> markerInterface() default Class.class;
String sqlSessionTemplateRef() default "";
String sqlSessionFactoryRef() default "";
Class<? extends MapperFactoryBean> factoryBean() default MapperFactoryBean.class;
String lazyInitialization() default "";
}
github工程地址:https://github.com/nestorbian/spring-boot-examples/tree/master/import-annotation