Spring @Import 注解用法

原文(简单修改):Spring 注解之 @Import 注解的三种使用方式

1、@Import 注解简介

@Import 只能用在类上,用于把实例加入 Spring 的 IOC 容器中。

下面是 @Import 注解的定义,其接收一个 Class 数组类型的参数:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Import {
	Class<?>[] value();
}

@Import 注解有三种用法,包括:

  1. 直接填 Class 数组方式

  2. ImportSelector 方式【重点】

  3. ImportBeanDefinitionRegistrar 方式

2、@Import 的三种用法

2.1、第一种用法:直接填 Class 数组

直接填对应的 Class 数组,Class 数组可以有 0 到多个。语法如下:

@Import({ 类名.class, 类名.class... })
public class TestDemo {

}

Spring 将按传给 @Import 注解的 Class 初始化实例并将其加入到 Spring 容器中,bean 名称是该类的全类名

2.2、第二种用法:ImportSelector 方式【重点】

这种方式的前提就是一个类要实现 ImportSelector 接口。比如创建 MyImportSelector 类并实现 ImportSelector 接口:

public class MyImportSelector implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        return new String[0];
    }
}

分析:

  • selectImports 方法的返回值就是我们实际上要导入到容器中的组件全类名数组【重点】
  • 其参数 AnnotationMetadata 表示当前被 @Import 注解给标注的所有注解信息

需要注意的是 selectImports 方法可以返回空数组但是不能返回 null,否则会报空指针异常。


具体用法如下:

第一步:创建 MyImportSelector 类并实现 ImportSelector 接口,这里用于演示就添加一个全类名给其返回值:

public class MyImportSelector implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        return new String[]{"com.example.Test.TestDemoBean"};
    }
}

第二步:编写 TestDemo 类,并标注上使用 ImportSelector 方式的 MyImportSelector 类:

@Configuration
@Import({MyImportSelector.class})
public class TestDemo {
}

第三步:编写打印容器中的组件测试类:

/**
 * 打印容器中的组件测试
 */
public class AnnotationTestDemo {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(TestDemo.class);  // 这里的参数代表要做操作的类

        String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
        for (String name : beanDefinitionNames){
            System.out.println(name);
        }

    }
}

运行结果将会看到 TestDemoBean 这个类,因为 @Import 注解的参数是数组,所以可以同时导入多个类,这里只导入了一个类。

2.3、第三种用法:ImportBeanDefinitionRegistrar 方式

同样是一个接口,类似于第二种 ImportSelector 用法,相似度 80%,只不过这种更灵活,具体如下:

第一步:创建 MyBeanDefinitionRegistrar 类并实现 ImportBeanDefinitionRegistrar 接口

public class MyBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
	// 该实现方法默认为空
    @Override
    public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
      
    }
}

参数分析:

  • 第一个参数:annotationMetadata 和之前的 ImportSelector 参数一样都是表示当前被 @Import 注解给标注的所有注解信息
  • 第二个参数表示用于注册 bean

第二步:编写代码,自定义注册 bean

public class MyBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
        // 指定 bean 定义信息(包括 bean 的类型、作用域...)
        RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(TestDemoBean.class);
        // 注册一个 bean 指定 bean 名字(id)
        beanDefinitionRegistry.registerBeanDefinition("TestDemoBean", rootBeanDefinition);
    }
}

第三步:编写 TestDemo 类,并标注上使用 ImportBeanDefinitionRegistrar 方式的 MyBeanDefinitionRegistrar 类

@Import({MyBeanDefinitionRegistrar.class})
public class TestDemo {
}

运行后,容器中就会有 TestDemoBean 这个 bean,id 为 TestDemoBean。

3、@Import 注解的三种使用方式总结

第一种用法:@Import({ 类名.class, 类名.class... }):容器会自动注册类对应 bean,id 默认是全类名

第二种用法:ImportSelector:返回需要导入的组件的全类名数组,SpringBoot 底层用得特别多【重点】。

第三种用法:ImportBeanDefinitionRegistrar:手动注册 bean 到容器。

posted @ 2024-11-28 22:05  Higurashi-kagome  阅读(19)  评论(0编辑  收藏  举报