敞开成长之旅!这是我参与「日新方案 12 月更文挑战」的第17天,点击检查活动概况
1、@ComponentScan
1.1 界说
@ComponentScan,是来自Spring结构的一个注解
- 它的作用是对 指定的package进行扫描,找到其中符合条件的类,默认是搜索被注解@Component修改的装备类
- 经过特点basePackages或basePackageClasses,来指定要进行扫描的package
- 如果未指定package,则默认扫描当前@ComponentScan所润饰的类所在的package
1.2 举例
@ComponentScan
public class Application {
}
@ComponentScan(basePackages = {"com.xx.code", "com.yy.code"})
public class Application {
}
@Component(excludeFilters = {
@ComponentScan.Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@ComponentScan.FIlter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class)
})
public class Application {
}
2、@Import
2.1 界说
@Import,是来自Spring结构的一个注解
- 它的作用是提供了一种显式地从其它当地加载装备类的办法,这样能够防止运用性能较差的组件扫描(Component Scan)
- 支撑导入:
- 一般类
- 接口ImportSelector的完成类
- 接口ImportBeanDefinitionRegistrar的完成类
2.2 导入一般类
能够经过@Import导入一个一般类,效果类似于这个一般类被注解@Component所润饰
public class A {
}
public class ConfigA {
@Bean
public A a() {
return new A();
}
}
@Configuration
@Import(ConfigA.class)
public class ConfigB {
}
public class Test01Main {
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(ConfigB.class);
// 现在Bean ConfigA 和 A 都在IoC容器中,是可用的
ConfigA ca = ctx.getBean(ConfigA.class);
A a = ctx.getBean(A.class);
System.out.println(ca.getClass().getSimpleName());
System.out.println(a.getClass().getSimpleName());
}
}
2.3 注解@Import导入接口ImportSelector完成类
能够经过@Import导入一个接口ImportSelector完成类。接口ImportSelector中有一个selectImports办法,它的返回值是一个字符串数组,数组中的每个元素分别代表一个将被导入的装备类的全限定名。运用该特性咱们能够给IoC容器动态地导入多个装备类。
public class Tiger {
}
public class ZooConfig {
@Bean
public Tiger tiger() {
return new Tiger();
}
}
public class ZooImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[] {"com.example.springboot_12.test02.ZooConfig"};
}
}
@Configuration
@Import({ZooImportSelector.class})
public class ConfigB02 {
}
public class Test02Main {
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(ConfigB.class);
// 现在Bean ZooConfig 和 Tiger 都在IoC容器中,是可用的
ZooConfig zc = ctx.getBean(ZooConfig.class);
Tiger t = ctx.getBean(Tiger.class);
System.out.println(zc.getClass().getSimpleName());
System.out.println(t.getClass().getSimpleName());
}
}
2.4 注解@import导入接口ImportBeanDefinitionRegistrar完成类
能够经过@Import导入一个接口ImportBeanDefinitionRegistrar的完成类。经过它,咱们能够手动将多个BeanDefinition注册到IoC容器中,然后完成个性化的定制。运用该特性咱们能够给IoC容器动态地导入多个BeanDefinition。
public class Dog {
}
public class ZooRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata am, BeanDefinitionRegistry bdr) {
GenericBeanDefinition gbd = new GenericBeanDefinition();
gbd.setBeanClass(Dog.class);
bdr.registerBeanDefinition("dog", gbd);
}
}
@Configuration
@Import({ZooRegistrar.class})
public class ConfigB03 {
}
public class Test03Main {
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(ConfigB03.class);
// 现在Bean Dog 在IoC容器中,是可用的
Dog d = ctx.getBean("dog", Dog.class);
System.out.println(d.getClass().getSimpleName());
}
}
3、总结
总结SpringBoot加载装备类的办法
- 运用注解 @ComponentScan
- 运用注解@Import
- 导入一般类
- 导入选择器 ImportSelector
- 导入注册器 ImpotBeanDefinitionRegistrar
应该运用哪种办法来加载SpringBoot的主动装备类呢?
首先扫除注解@ComponentScan。由于运用它很不方便,开发人员需求记住每个第三方jar包中的package名称,然后把它们写到应用程序中,这不符合开箱即用。
@Import更不能运用了,它还需求开发人员记住第三方jar包中的具体类名。
运用@Import导入一个BeanDefinition注册器,也不恰当,BeanDefinition注册器的设计方针是对@Bean办法的一个补充,它针对的是BeanDefinition层面的,并不是用来导入装备类的。
运用@Import导入一个选择器ImportSelector,它十分合适用来完成主动装备。 SpringBoot运用注解@Import 导入一个ImportSelector然后完成了主动装备的功能。