五、Spring中的@Import注解


一、使用@Import注解導入組件

@Import注解的作用是給容器中導入組件,回顧下我們給容器中導入組件的方式,可以通過Spring的xm配置方式,可以通過注解,如@Component等,也可以通過java配置類的方式給容器中導入注解,今天來介紹另一個注解,其作用也是給容器中導入組件。


其用法非常簡單,我們舉個小例子 ,

配置類MainConfig2

@Configuration
@Import({Color.class,Red.class})//將這兩個類導入到容器中
//@Import導入組件,id默認是組件的全類名
public class MainConfig2 {


}

其中Color.class和Red.class就是兩個非常普通的java類,不必關心這兩個類有何特殊的。

我們寫個測試方法,用於遍歷下容器中bean組件的名字

@Test
public void printBeans(AnnotationConfigApplicationContext applicationContext){
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);
		String[] definitionNames = applicationContext.getBeanDefinitionNames();
		for (String name : definitionNames) {
			System.out.println(name);
		}
	}

我們關注下打印的結果:

mainConfig2
com.atguigu.bean.Color //@Import導入組件,id默認是組件的全類名
com.atguigu.bean.Red

二、@Import導入ImportSelector

上面可以看到 ,這種方式進行導入呢?還是略微麻煩了點,如果組件很多,也是比較麻煩的,所以呢,我們也可以結合ImportSelector來使用

首先,我們再寫兩個類,叫做Bule.javaYellow.java,不必關心類里有什么,哪怕是個空類也是可以的,我們只關心其是否能被正確注入到組件之中

那如何使用ImportSelector呢?

這是一個接口,繼承並實現即可。

//自定義邏輯返回需要導入的組件
public class MyImportSelector implements ImportSelector {

	//返回值,就是到導入到容器中的組件全類名
	//AnnotationMetadata:當前標注@Import注解的類的所有注解信息
	@Override
	public String[] selectImports(AnnotationMetadata importingClassMetadata) {
		//方法不要返回null值
		return new String[]{"com.atguigu.bean.Blue","com.atguigu.bean.Yellow"};
	}
}

關於這個導入選擇器,從這個方法名selectImports就可以看出,,是選擇性的導入的意思,所以在這個方法中,我們是可以通過編寫不同的邏輯,來返回我們需要導入的組件,那上面自定義的選擇導入器,只是為了演示,所以沒有具體的條件判斷等,可自行擴展,返回需要導入的組件BlueYellow

,然后將這個類加入到@Import注解的參數中,就像這樣

@Configuration
@Import({Color.class,Red.class,MyImportSelector.class})//將這兩個類導入到容器中
//@Import導入組件,id默認是組件的全類名
public class MainConfig2 {
}

我們還是用剛才的測試方法打印下結果:

mainConfig2
com.atguigu.bean.Color
com.atguigu.bean.Red
com.atguigu.bean.Blue //Blue被注冊進了容器中
com.atguigu.bean.Yellow // Yellow被注冊進了容器中

以上就是ImportSelector接口的使用,是比較簡單的。

三、@Import導入ImportBeanDefinitionRegistrar

ImportBeanDefinitionRegistrarImportSelector的使用大致相同,它是接口,我們只需實現它,並將它作為參數,放在@Import中即可,。

自定義實現類MyImportBeanDefinitionRegistrar

public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {

	/**
	 * AnnotationMetadata:當前類的注解信息
	 * BeanDefinitionRegistry:BeanDefinition注冊類;
	 * 		把所有需要添加到容器中的bean;調用
	 * 		BeanDefinitionRegistry.registerBeanDefinition手工注冊進來
	 */
	@Override
	public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
		
		boolean definition = registry.containsBeanDefinition("com.atguigu.bean.Red");
		boolean definition2 = registry.containsBeanDefinition("com.atguigu.bean.Blue");
		if(definition && definition2){
			//指定Bean定義信息;(Bean的類型,Bean。。。)
			RootBeanDefinition beanDefinition = new RootBeanDefinition(RainBow.class);
			//注冊一個Bean,指定bean名
			registry.registerBeanDefinition("rainBow", beanDefinition);
		}
	}

}

在配置類的@Import注解中加入這個自定義的類

@Configuration
@Import({Color.class,Red.class,MyImportSelector.class,MyImportBeanDefinitionRegistrar.class})//將這兩個類導入到容器中
//@Import導入組件,id默認是組件的全類名
public class MainConfig2 {
}

依舊使用剛才的測試方法打印一下

mainConfig2
com.atguigu.bean.Color
com.atguigu.bean.Red
com.atguigu.bean.Blue
com.atguigu.bean.Yellow
rainBow // 自定義MyImportBeanDefinitionRegistrar的注冊組件

對比后兩種注冊方法,我們發現,ImportBeanDefinitionRegistrar是沒有返回值的,另外它多了一個參數BeanDefinitionRegistry,也就是可以直接在方法中就注冊bean。

四、詳細分析

我們來看下ImportBeanDefinitionRegistrar的源碼,

package org.springframework.context.annotation;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.core.type.AnnotationMetadata;
public interface ImportBeanDefinitionRegistrar {
	/**
	 * Register bean definitions as necessary based on the given annotation metadata of
	 * the importing {@code @Configuration} class.
	 * <p>Note that {@link BeanDefinitionRegistryPostProcessor} types may <em>not</em> be
	 * registered here, due to lifecycle constraints related to {@code @Configuration}
	 * class processing.
	 * @param importingClassMetadata annotation metadata of the importing class
	 * @param registry current bean definition registry
	 */
	public void registerBeanDefinitions(
			AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry);

}

我們看下方法第一個參數AnnotationMetadata importingClassMetadata,這個是注解的元信息,即配置類上所有注解的信息,然后可以在MyImportBeanDefinitionRegistrar自定義我們自己需要的邏輯,動態注冊bean、

不同的是,這個類通過BeanDefinitionRegistry本身就可以注冊組件。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM