一、认识@Import注解
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Import { Class<?>[] value(); }
@Import注解的用法
导入一个或多个Bean
导入@Configuration类
导入ImportSelector的实现类
导入ImportBeanDefinitionRegistrar的实现类
我们在springboot中可以看到大量的@Import在自动配置类中出现,对于我们实际业务开发中是很少使用到的,那么它究竟为什么出现以及目的是什么呢?
@Import可以用来辅助导入bean,此时有个问题既然有了@Component以及@ComponentScan()为什么还需要它呢?
一般@ComponentScan()只能扫描你当前项目下标注@Controller的实体类以及其他配置类,若是有第三方导入进来或者不在自动扫描包下的实体类就无法被扫描,那么也就不会被Spring容器接管。此时就可以通过@Import注解来进行引入了!!!
二、实操
前置准备
引入依赖:
<dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.3.7</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.3.6</version> </dependency> </dependencies>
实现
上面一中介绍到@Import可以配合四种方式来进行导入对应的class,来让spring容器生成实体类并进行管理,这里的话在pojo中创建四个实体类如TestBean1、xxx…、TestBean4,其他三个类是用来进行配合@Import来进行导入的
四个实体类:
public class TestBean1 { @Override public String toString() { return super.toString()+"--我是TestBean1"; } } public class TestBean2 { @Override public String toString() { return super.toString()+"--我是TestBean2"; } } public class TestBean3 { @Override public String toString() { return super.toString()+"--我是TestBean3"; } } public class TestBean4 { @Override public String toString() { return super.toString()+"--我是TestBean4"; } }
四种需要配合@Import导入的实体类
//方式一:直接传入class //方式二:@Configuration+@Bean @Configuration public class ImportBeanByConfig { @Bean public TestBean2 testBean2(){ return new TestBean2(); } } //方式三:实现ImportBeanDefinitionRegistrar重写方法来进行手动注册 public class ImportBeanByImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar { public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(TestBean4.class); registry.registerBeanDefinition("TestBean4", rootBeanDefinition); } } //方式四:实现ImportSelector重写方法将多个class以数组形式返回 public class ImportBeanByImportSelector implements ImportSelector { public String[] selectImports(AnnotationMetadata annotationMetadata) { return new String[]{"pojo.TestBean3"}; } }
Spring配置类:借助该类进行打开自动扫描包
@Configuration @ComponentScan("scan") //自动扫描改包下 public class SpringConfig { }
自动扫描包下的两个类:
ImportTest.java:用来导入那些不是自动包下的类 @Import({ TestBean1.class, //方式一:直接引入class类 ImportBeanByConfig.class, //方式二:将@Configuration+@Bean的类交由Spring容器管理 ImportBeanByImportSelector.class, //方式三:对于实现ImportSelector接口并重写selectImports方法返回的class交由Spring管理 ImportBeanByImportBeanDefinitionRegistrar.class //方式四:实现ImportBeanDefinitionRegistrar并重写方法,方法中进行注册 }) @Configuration public class ImportTest { }
CommonController.java:用于检测@Import导入的class被容器接管并实例化
@Component public class CommonController { @Autowired(required = false) private TestBean1 testBean1; @Autowired(required = false) private TestBean2 testBean2; @Autowired(required = false) private TestBean3 testBean3; @Autowired(required = false) private TestBean4 testBean4; public void printImportBeanInfo(){ System.out.println(testBean1); System.out.println(testBean2); System.out.println(testBean3); System.out.println(testBean4); } }
最终的测试类:用于检验效果
public class Test { public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class); CommonController controller = (CommonController) context.getBean("commonController"); System.out.println(controller); controller.printImportBeanInfo(); } }