zoukankan      html  css  js  c++  java
  • 五、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本身就可以注册组件。

    你所看得到的天才不过是在你看不到的时候还在努力罢了!
  • 相关阅读:
    [论文笔记]CVPR2017_Joint Detection and Identification Feature Learning for Person Search
    [论文笔记]Objects as Points
    [论文笔记]ICCV2017_SVDNet for Pedestrian Retrieval
    [论文笔记]ICPR2016_Person Re-Identification Using CNN Features Learned from Combination of Attributes
    VMware ESXI6.0服务器安装系列:RAID设置
    LVM基础详细说明及动态扩容lvm逻辑卷的操作记录
    调用对象 “ha-datastoresystem”的“HostDatastoreSystem.QueryVmfsDatastoreCreateOptions” 失败。
    动态扩容lvm逻辑卷的操作记录
    Kubernetes之Flannel介绍
    Linux服务器同步网络时间
  • 原文地址:https://www.cnblogs.com/heliusKing/p/11372014.html
Copyright © 2011-2022 走看看