spring注解之@Import注解的三种使用方式
Posted codingjav
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了spring注解之@Import注解的三种使用方式相关的知识,希望对你有一定的参考价值。
1、@Import注解须知
1、@Import只能用在类上 ,@Import通过快速导入的方式实现把实例加入spring的IOC容器中
2、加入IOC容器的方式有很多种,@Import注解就相对很牛皮了,@Import注解可以用于导入第三方包 ,当然@Bean注解也可以,但是@Import注解快速导入的方式更加便捷
3、@Import注解有三种用法
2、@Import的三种用法
@Import的三种用法主要包括:
1、直接填class数组方式
2、ImportSelector方式【重点】
3、ImportBeanDefinitionRegistrar方式
2.1、第一种用法:直接填class数组
直接填对应的class数组,class数组可以有0到多个。
语法如下:
@Import({ 类名.class , 类名.class... })
public class TestDemo {
}
对应的import的bean都将加入到spring容器中,这些在容器中bean名称是该类的全类名 ,比如com.yc.类名
2.2、第二种用法:ImportSelector方式【重点】
这种方式的前提就是一个类要实现ImportSelector接口,假如我要用这种方法,目标对象是Myclass这个类,分析具体如下:
创建Myclass类并实现ImportSelector接口
/**
* @import 注解中使用ImportSelector
* 自定义逻辑,返回需要导入的组件
*/
public class MySelector implements ImportSelector {
/**
* 返回值为需要导入到容器中的bean的全类名数组
* @param annotationMetadata
* @return
*/
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
Map<String, Object> attributes = annotationMetadata.getAnnotationAttributes(MyScan.class.getName());
if (CollectionUtils.isEmpty(attributes)) {
return new String[0];
}
String[] basePackages = (String[]) attributes.get("basePackages");
ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false);
scanner.addIncludeFilter(new AssignableTypeFilter(Student.class));//这里实现包含,相当@ComponentScan includeFilters
scanner.addIncludeFilter(new AssignableTypeFilter(User.class));
//scanner.addExcludeFilter(new AssignableTypeFilter(Object.class));//这里可以实现排除,相当@ComponentScan excludeFilters
Set<String> classs = new HashSet<>();
for (String basePackage : basePackages) {
Set<BeanDefinition> components = scanner.findCandidateComponents(basePackage);
components.forEach(bean -> classs.add(bean.getBeanClassName()));
}
return classs.toArray(new String[0]);
}
}
分析实现接口的selectImports方法中的:
-
1、返回值:就是我们实际上要导入到容器中的组件全类名【重点 】
-
2、参数:AnnotationMetadata表示当前被@Import注解给标注的所有注解信息【不是重点】
需要注意的是selectImports方法可以返回空数组但是不能返回null,否则会报空指针异常!
以上分析完毕之后,具体用法步骤如下:
编写自定义注解,在启动类引入即可。
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Import(MySelector.class)
public @interface MyScan {
@AliasFor("basePackages")
String[] value() default {};
@AliasFor("value")
String[] basePackages() default {};
}
编写启动类打印组件测试类:
@MyScan(basePackages = {"com.kingoe.skill.entity"})
@SpringBootApplication
public class SkillApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(SkillApplication.class, args);
String[] beanDefinitionNames = context.getBeanDefinitionNames();
for (String name : beanDefinitionNames){
System.out.println(name);
}
}
}
2.3、第三种用法:ImportBeanDefinitionRegistrar方式
同样是一个接口,类似于第二种ImportSelector用法,只不过这种用法比较自定义化注册,具体如下:
第一步:创建MyTest2类并实现ImportBeanDefinitionRegistrar接口
public class MyTest2 implements ImportBeanDefinitionRegistrar {
//该实现方法默认为空
@Override
public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(Test4.class);
beanDefinitionRegistry.registerBeanDefinition("TestDemo4444",rootBeanDefinition); }
}
参数分析:
-
第一个参数:annotationMetadata 和之前的ImportSelector参数一样都是表示当前被@Import注解给标注的所有注解信息
-
第二个参数表示用于注册定义一个bean
第二步:编写TestDemo 类,并标注上使用ImportBeanDefinitionRegistrar方式的MyTest2类
@Import({MyTest2.class,Myclass2.class})
public class TestDemo {
@Bean
public AccountDao2 accountDao222(){
return new AccountDao2();
}
}
3、@Import注解的三种使用方式总结
第一种用法:
@Import
({ 要导入的容器中的组件 } ):容器会自动注册这个组件,id默认是全类名第二种用法:
ImportSelector
:返回需要导入的组件的全类名数组,springboot底层用的特别多【重点 】第三种用法:
ImportBeanDefinitionRegistrar
:手动注册bean到容器
以上三种用法方式皆可混合在一个@Import中使用,特别注意第一种和第二种都是以全类名的方式注册,而第三中可自定义方式。
@Import注解本身在springboot中用的很多,特别是其中的第二种用法ImportSelector方式在springboot中使用的特别多,尤其要掌握!
以上是关于spring注解之@Import注解的三种使用方式的主要内容,如果未能解决你的问题,请参考以下文章