@Import详解及@Import注入对象的四种方式

在Java中,@Import注解是用于引入其他配置类或Bean的注解。它可以帮助将特定的配置类或Bean注册到Spring容器中,使其可供应用程序使用。

@Import详解

  @Import注解可以用在@Configuration注解的类上,也可以用在普通的类上。它作为一个元注解,可以标记其他注解,例如@ImportResource@ImportSelector@ImportBeanDefinitionRegistrar等。

使用@Import注解,可以将以下内容导入到Spring容器中:

  1. 配置类(Configuration Class):通过导入其他的配置类,可以将其内部定义的Bean注册到容器中。
  2. 普通类(Non-configuration Class):将普通的类作为Bean导入到Spring容器中。

@Import源码


@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Import {

   /**
    * {@link Configuration @Configuration}, {@link ImportSelector},
    * {@link ImportBeanDefinitionRegistrar}, or regular component classes to import.
    */
   Class<?>[] value();

}
 

从注释来看,@Import注解只可以标注在类上,可以结合 @Configuration注解、ImportSelector、ImportBeanDefinitionRegistrar一起使用,也可以导入普通的类。

因此,@Import的使用方式有4种:直接导入类,导入配置类来导入Bean,导入 ImportSelector 的实现类,导入 ImportBeanDefinitionRegister 的实现类。需要注意的是:ImportSelector、ImportBeanDefinitionRegistrar 这两个接口都必须依赖于 @Import 一起使用,而 @Import 可以单独使用。

@Import的实现原理

@Import注解的实现原理涉及到Spring框架的组件扫描、Bean注册和依赖注入等机制

  1. 组件扫描:Spring框架会通过组件扫描机制,自动扫描并加载带有@Configuration注解或其他指定注解的配置类,将它们识别为配置类。

  2. 注册配置类:当一个配置类被识别后,Spring会将其实例化为一个Bean,并将其注册到容器中。这样,配置类内部定义的所有Bean都可以由Spring容器进行管理。

  3. 处理@Import注解:当在配置类上使用@Import注解时,Spring会解析注解的参数,根据参数的不同类型进行相应的处理。

    • 导入其他配置类:如果@Import的参数是其他配置类(例如@Configuration注解的类),Spring会将导入的配置类也加入到容器中,使得被导入的配置类内部定义的Bean也可以被管理。

    • 导入普通类:如果@Import的参数是普通类,则Spring会将该类实例化为一个Bean,并注册到容器中。

    • 导入实现了ImportSelector的类:如果@Import的参数是实现了ImportSelector接口的类,Spring会调用ImportSelector接口的selectImports()方法,根据返回的类名数组将相应的类注册为Bean。这样,可以根据特定的逻辑动态选择需要导入的类。

    • 导入实现了ImportBeanDefinitionRegistrar的类:如果@Import的参数是实现了ImportBeanDefinitionRegistrar接口的类,Spring会调用ImportBeanDefinitionRegistrar接口的registerBeanDefinitions()方法,通过编程方式注册Bean定义到容器中。这样,可以通过自定义的逻辑来注册额外的Bean。

        通过以上步骤,@Import注解使得我们能够方便地导入其他配置类、普通类或实现了ImportSelectorImportBeanDefinitionRegistrar接口的类,并将它们注册到Spring容器中,从而实现Bean的管理和依赖注入。

需要导入的类


public class HelloImport {
  
    public void test() {
       System.out.println("hello JF");
    }
}

1、直接导入类

@Import(HelloImport.class)
public class SpringTestApplication {

    public static void main(String[] args) {
        //1.通过AnnotationConfigApplicationContext创建spring容器,参数为@Import标注的类
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringTestApplication.class);
        HelloImport helloImport = applicationContext.getBean(HelloImport.class);
        elloImport.test();
    }
}

项目中常用以下方式:


@Import(HelloImport.class)
@Configuration
public class ConfigTest { 
}

2、导入配置类注入Bean

@Configuration
public class HelloImportConfiguration {

    @Bean
    public HelloImport helloImport() {
        return new HelloImport();
    }
}

@Import(HelloImportConfiguration.class)
public class SpringTestApplication {

    public static void main(String[] args) {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringTestApplication.class);
        HelloImport helloImport = applicationContext.getBean(HelloImport.class);
        helloImport.test();
    }
}

这种方式的使用场景是配置类无法被直接扫描到。

3、导入 ImportSelector 实现类

ImportSelector是一个接口,实现这个接口需要重写selectImports方法。selectImports方法会返回一个String数组,它包含的元素是需要被导入到容器中的类的全限定名。


public class HelloImportSelector implements ImportSelector {
    /**
     * 返回需要导入的类名的数组,可以是任何普通类,配置类(@Configuration、@Bean、@CompontentScan等标注的类)
     * @importingClassMetadata:用来获取被@Import标注的类上面所有的注解信息
     */
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        List list = new ArrayList<>();
        list.add("intl.skw.test.HelloImport");
        return StringUtils.toStringArray(list);
    }
}

@Import(HelloImportSelector.class)
public class SpringTestApplication {

    public static void main(String[] args) {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringTestApplication.class);
        HelloImport helloImport = applicationContext.getBean(HelloImport.class);
        helloImport.test();
    }
}

4、导入 ImportBeanDefinitionRegistrar 实现类

当类实现了 ImportBeanDefinitionRegistrar 接口,就可以拿到注册器,可以向容器中注册任何的Bean,并且可以对Bean添加属性。

public class HelloImportDefinitionRegistrar implements ImportBeanDefinitionRegistrar {

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(HelloImport.class)
                .getBeanDefinition();
        registry.registerBeanDefinition("HelloImport", beanDefinition);
    }
}

@Import(HelloImportDefinitionRegistrar.class)
public class SpringTestApplication {

    public static void main(String[] args) {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringTestApplication.class);
        HelloImport helloImport = applicationContext.getBean(HelloImport.class);
        helloImport.test();
    }
}

猜你喜欢

转载自blog.csdn.net/Ascend1977/article/details/131391041