Spring的import注解解析及使用场景

一、导言

        在spring框架下做开发时,会给容器中导入组件,通常我们给容器中注入组件的方式,可以通过Spring的xml配置方式,也可以通过注解,如@Component等,也可以通过java配置类的方式给容器中导入,@Import也是常见的导入注解(组件如类实例),可以用来动态创建bean。        

二、使用


1. 从spring、springboot的很多Enable前缀的注解可以看出,Enable注解使用了Import注解;
2. 三种Import注解用法;
3. spring源码,揭示Import注解的工作原理;
4. 实战通过Import注解动态创建bean实例;

1、Enable前缀的注解
有很多注解都以Enable为前缀,例如配置调度的注解EnableScheduling,其源码如下 :


从以上代码可见,@Import(SchedulingConfiguration.class),通过此注解spring容器会创建SchedulingConfiguration实例。

再如如EnableBatchProcessing、EnableCaching、EnableDiscoveryClient等,也都是通过Import来生效的,这种方式值得我们学习,在公司的通用组件、通用模块等开发中,也能用类似方式来对bean实例导入。

2、3种使用
在@Import注解的参数中可以填写类名,例如@Import(Abc.class),根据类Abc的不同类型,spring容器有以下四种处理方式:
1. 如果Abc类实现了ImportSelector接口,spring容器就会实例化Abc类,并且调用其selectImports方法;
2. 如果Abc类实现了ImportBeanDefinitionRegistrar接口,spring容器就会实例化Abc类,并且调用其registerBeanDefinitions方法;
3. 如果Abc没有实现ImportSelector、DeferredImportSelector、ImportBeanDefinitionRegistrar等其中的任何一个,spring容器就会实例化Abc类。

2.1、直接导入,适用于少数类实例导入spring容器,一般在Enable***注解使用非常多。

@Import({A.class, B.class})

2.2、如果组件很多,我们也可以结合ImportSelector来使用


public class MyImportSelector implements ImportSelector {
 
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
 
        return new String[]{"com.test.entity.A","com.test.entity.B"};
    }
}
        这是个导入选择器,从这个方法名 selectImports 就可以看出,是选择性的导入的意思,所以在这个方法中,我们是可以通过编写不同的逻辑,来返回我们需要导入的组件,上面自定义的选择导入器,只是为了演示,所以没有具体的条件判断等,可自行扩展,返回需要导入的组件A和B,然后将这个类加入到@Import注解的参数中,如下代码

@Import({E.class, F.class,MyImportSelector.class}

2.3、实现接口ImportBeanDefinitionRegistrar

   ImportBeanDefinitionRegistrar与ImportSelector的使用大致相同,它是接口,我们只需实现它,并将它作为参数,放在@Import中即可。

2.3.1. 创建MyImportBeanDefinitionRegistrar类

public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
 
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
 
        boolean definition = registry.containsBeanDefinition("
com.test.entity.C");
        boolean definition2 = registry.containsBeanDefinition("
com.test.entity.D");
        if(definition && definition2){
            //指定Bean定义信息
            RootBeanDefinition beanDefinition = new RootBeanDefinition(R.class);
            //注册一个Bean,指定bean名
            registry.registerBeanDefinition("R", beanDefinition);
        }
 
    }

2.3.2、使用import ,就可以把R的实例导入spring容器

@Import({E.class, F.class,MyImportSelector.class,MyImportBeanDefinitionRegistrar.class})

2.4、和ImportSources的区别

           @Import注解是引入带有@Configuration的java类。

           @ImportResource是引入spring配置文件.xml

三、源码分析

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值