Spring中@Import註解的使用

口袋裡的貓發表於2021-05-13

Spring中@Import註解的使用

@Import註解算是SpringBoot自動配置原理中一個很重要的註解

認識@Import註解

?先看一下原始碼

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

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

}

@Import表示要匯入的一個或多個@Configuration類

看註釋value通常是一個普通的元件,ConfigurationImportSelectorImportBeanDefinitionRegistrar

搭建專案結構用於測試

  1. 先建立一個maven工程
  2. 加入依賴
<dependencies>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.18</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>4.3.24.RELEASE</version>
    </dependency>
</dependencies>
  1. 編寫測試程式碼

Tom.java

@Data
public class Tom {
    private String color;
    private Integer age;
}

AppConfig.java

@Configuration
public class AppConfig {
}

App.java

public class App {
    public static void main(String[] args) {
        // 建立容器
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        // 獲取bean
        Tom tom = context.getBean(Tom.class);
        System.out.println(tom);
    }
}

@Import用法

第一種普通元件

@Import({ 要匯入的容器中的元件 } )

CustomConfiguration.java

@Configuration
public class CustomConfiguration {
    @Bean
    public Tom tom() {
        Tom tom = new Tom();
        tom.setAge(11);
        tom.setColor("紅色");
        return tom;
    }
}

AppConfig.java加上@Import({ CustomConfiguration.class })

@Import({ CustomConfiguration.class })
@Configuration
public class AppConfig {
}

這個時候執行App已經可以獲取到Tom

第二種ImportSelector

CustomSelector.java

public class CustomSelector implements ImportSelector {

    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[] { "com.moli.pojo.Tom" };
    }
}

AppConfig.java加上@Import({ CustomRegistrar.class })

@Import({ CustomRegistrar.class })
@Configuration
public class AppConfig {
}

這個時候執行App已經可以獲取到Tom

第三種ImportBeanDefinitionRegistrar

CustomRegistrar.java

public class CustomRegistrar implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(Tom.class);
        builder.setScope(BeanDefinition.SCOPE_SINGLETON);
        builder.addPropertyValue("color", "灰色");
        builder.addPropertyValue("age", "12");
        registry.registerBeanDefinition("tom", builder.getBeanDefinition());
    }
}

AppConfig.java加上@Import({ CustomSelector.class })

@Import({ CustomSelector.class })
@Configuration
public class AppConfig {
}

這個時候執行App已經可以獲取到Tom

最佳搭檔 - @Import通用形式

在開源軟體中大部分@Import中是伴隨著一個@EnableXXX使用的

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import({ CustomRegistrar.class })
public @interface EnableTom {
}

AppConfig.java加上@EnableTom

@EnableTom
@Configuration
public class AppConfig {
}

這樣看起來,是不是有那味了。

其實SpringBoot的自動配置就是@Import的一個應用

@SuppressWarnings("deprecation")
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(EnableAutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
    ...
}

總結

直白一點使用@Import註解可以快速把例項加入Spring的IOC容器中

其實這三種用法也算是一種用法,就是匯入一個類到容器,容器根據類的註解型別等資訊對不同類進行不同處理;

方法一:匯入一個Configuration元件,元件建立了一個Tom類的Bean;

方法二:CustomSelector返回的類的全限定類名,實際上要匯入到容器中的元件全類名;

方法三:ImportBeanDefinitionRegistrar類似於第二種ImportSelector用法,只不過這種用法能自定義化註冊,往容器內注入一個BeanDefinition,然後BeanDeiniton在容器內轉為一個例項bean;

文中示例程式碼Gitee

相關文章