【Spring註解驅動開發】使用@Import註解給容器中快速匯入一個元件

冰河團隊發表於2020-06-10

寫在前面

我們可以將一些bean元件交由Spring管理,並且Spring支援單例項bean和多例項bean。我們自己寫的類,可以通過包掃描+標註註解(@Controller、@Servcie、@Repository、@Component)的形式將其註冊到IOC容器中,如果不是我們自己寫的類,比如,我們在專案中引入了一些第三方的類庫,此時,我們需要將這些第三方類庫中的類註冊到Spring容器中,該怎麼辦呢?此時,我們就可以使用@Bean和@Import註解將這些類快速的匯入Spring容器中。接下來,我們來一起探討下如何使用@Import註解給容器中快速匯入一個元件。

專案工程原始碼已經提交到GitHub:https://github.com/sunshinelyz/spring-annotation

註冊bean的方式

向Spring容器中註冊bean通常有以下幾種方式:

  • 包掃描+標註註解(@Controller、@Servcie、@Repository、@Component),通常用於自己寫的類。
  • @Bean註解,通常用於匯入第三方包中的元件。
  • @Import註解,快速向Spring容器中匯入元件。

@Import註解概述

Spring 3.0之前,建立Bean可以通過xml配置檔案與掃描特定包下面的類來將類注入到Spring IOC容器內。而在Spring 3.0之後提供了JavaConfig的方式,也就是將IOC容器裡Bean的元資訊以java程式碼的方式進行描述。我們可以通過@Configuration與@Bean這兩個註解配合使用來將原來配置在xml檔案裡的bean通過java程式碼的方式進行描述

@Import註解提供了@Bean註解的功能,同時還有xml配置檔案裡標籤組織多個分散的xml檔案的功能,當然在這裡是組織多個分散的@Configuration

先看一下@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 , ImportSelector, ImportBeanDefinitionRegistrar 來使用,下面的or表示也可以把Import當成普通的Bean使用。

@Import只允許放到類上面,不能放到方法上。下面我們來看具體的使用方式。

@Import註解的使用方式

@Import註解的三種用法主要包括:

  • 直接填class陣列方式
  • ImportSelector方式【重點】
  • ImportBeanDefinitionRegistrar方式

注意:我們先來看第一種方法:直接填class陣列的方式,其他的兩種方式我們後面繼續講。

@Import匯入元件的簡單示例

沒有使用@Import註解的效果

首先,我們建立一個Department類,這個類是一個空類,沒有成員變數和方法,如下所示。

package io.mykit.spring.plugins.register.bean;

/**
 * @author binghe
 * @version 1.0.0
 * @description 測試@Import註解的bean
 */
public class Department {
}

接下來,我們先在SpringBeanTest類中建立testAnnotationConfig7()方法,輸出Spring容器中所有的bean,來檢視是否存在Department類對應的bean例項,以此來判斷Spring容器中是否註冊有Department類對應的bean例項。

@Test
public void testAnnotationConfig7(){
    ApplicationContext context = new AnnotationConfigApplicationContext(PersonConfig2.class);
    String[] names = context.getBeanDefinitionNames();
    Arrays.stream(names).forEach(System.out::println);
}

執行SpringBeanTest類的testAnnotationConfig7()方法,輸出的結果資訊如下所示。

org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
personConfig2
person
binghe001

可以看到Spring容器中並沒有Department類對應的bean例項。

使用@Import註解的效果

我們在PersonConfig2類上新增@Import註解,並將Department類標註到註解中,如下所示。

@Configuration
@Import(Department.class)
public class PersonConfig2 {

此時,我們再次執行SpringBeanTest類的testAnnotationConfig7()方法,輸出的結果資訊如下所示。

org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
personConfig2
io.mykit.spring.plugins.register.bean.Department
person
binghe001

可以看到,輸出結果中列印了io.mykit.spring.plugins.register.bean.Department,說明使用@Import匯入bean時,id預設是元件的全類名。

@Import註解支援同時匯入多個類,例如,我們再次建立一個Employee類,如下所示。

package io.mykit.spring.plugins.register.bean;
/**
 * @author binghe
 * @version 1.0.0
 * @description 測試@Import註解的bean
 */
public class Employee {
}

接下來,我們也將Employee類新增到@Import註解中,如下所示。

@Configuration
@Import({Department.class, Employee.class})
public class PersonConfig2 {

此時,我們再次執行SpringBeanTest類的testAnnotationConfig7()方法,輸出的結果資訊如下所示。

org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
personConfig2
io.mykit.spring.plugins.register.bean.Department
io.mykit.spring.plugins.register.bean.Employee
person
binghe001

可以看到,結果資訊中同時輸出了io.mykit.spring.plugins.register.bean.Department和io.mykit.spring.plugins.register.bean.Employee,說明Department類的bean例項和Employee類的bean例項都匯入到Spring容器中了。

好了,我們們今天就聊到這兒吧!別忘了給個在看和轉發,讓更多的人看到,一起學習一起進步!!

專案工程原始碼已經提交到GitHub:https://github.com/sunshinelyz/spring-annotation

寫在最後

如果覺得文章對你有點幫助,請微信搜尋並關注「 冰河技術 」微信公眾號,跟冰河學習Spring註解驅動開發。公眾號回覆“spring註解”關鍵字,領取Spring註解驅動開發核心知識圖,讓Spring註解驅動開發不再迷茫。

相關文章