文章目录
1. @Import 作用
将Bean实例加入IOC容器管理,常见的有以下几种方式:
- @Controller、@Service、@Repository、@Component、@Configuration 标记的类,并且被扫描到
- @Bean,导入的第三方包里的组件
- @Import,快速给容器导入一个组件
其中,@Import 导入组件也有以下三种方式
2. 方式一:@Import 直接导入
先来看个例子,当前有两个类A和B。 A没有加@Component因此不会加入Spring容器,B类会加入Spring容器,并且自动注入属性a。
public class A {
public A(){
System.out.println("调用A构造函数");
}
}
@Component
public class B {
@Autowired
private A a;
public B(){
System.out.println("调用B构造函数");
}
}
此时启动程序,抛出 NoSuchBeanDefinitionException
,原因是Spring容器内部找不到Bean A
如果我们希望在使用B类的时候再将A类注入容器,而不是一开始就通过@Component注入。name,@Import就派上用场了。修改class B代码,加上@Import试试
@Component
@Import(A.class)
public class B {
@Autowired
private A a;
public B(){
System.out.println("调用B构造函数");
}
}
重新启动程序,运行正常:
3. 方式二:ImportSelector 接口
定义一个类 MyImportSelector 实现 ImportSelector 接口,当前接口只有一个方法 selectImports。
public class MyImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
System.out.println("执行MyImportSelector");
return new String[]{
A.class.getName() };
}
}
然后修改B类,@Import改成导入 MyImportSelector.class
@Component
@Import({
MyImportSelector.class})
public class B {
@Autowired
private A a;
public B(){
System.out.println("调用B构造函数");
}
}
运行结果如下:
4. 方式三:ImportBeanDefinitionRegistrar 接口
该方法和方式二基本类似,也是通过实现接口方法自定义注入 Bean。
创建 MyImportBeanDefinitionRegistrar,实现 ImportBeanDefinitionRegistrar 接口
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
System.out.println("执行 MyImportBeanDefinitionRegistrar");
RootBeanDefinition beanDefinition = new RootBeanDefinition(A.class);
registry.registerBeanDefinition("A", beanDefinition);
}
}
然后修改B类的 @Import 如下:
@Component
@Import({
MyImportBeanDefinitionRegistrar.class})
public class B {
@Autowired
private A a;
public B(){
System.out.println("调用B构造函数");
}
}
运行后,输出结果如下: