spring扩展点三:@Import注解

本文介绍了Spring框架中的@Import注解,详细阐述了ImportBeanDefinitionRegistrar和ImportSelector的作用。@Import注解常用于框架中,通过ImportSelector或ImportBeanDefinitionRegistrar实现类注入bean。在解析过程中,会递归判断并处理bean,最终将所有beanDefinition存入集合。应用方面,@Import可直接引入普通bean,ImportSelector实现类或ImportBeanDefinitionRegistrar实现类。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

@Import注解的作用

说到@Import注解,必须要说的是下面这两个类
ImportSelector接口对应的实现方法中,需要返回一个数组,数组中,是要注入到spring容器中的class对应的全类名
ImportBeanDefinitionRegistrar接口的实现方法中,会提供BeanDefinitionRegistry对象,我们可以在方法中通过该对象自己注入到beanDefinitionMap中一个beanDefinition对象
这是这两个类的作用

在spring源码中,@Import注解是使用最多的,一点也不为过,其实在大部分的框架中,会看到每个框架会自定义好多注解,这些注解中,有一大部分都是利用了@Import注解来完成的,并且,通过@Import注解,注入的,一般都是ImportSelector或者是ImportBeanDefinitionRegistrar的实现类
关于这两个扩展点的原理,在前面的博客中spring源码:@Import注解
,有记录过,所以,就不做过多的解释,大致再总结一下吧

1、在spring源码中,将一个class对象转换成一个spring容器所能接收的bean对象,首先要先将class对象转换为beanDefinition对象,在转换过程中,通常是通过@ComponentScan注解来完成扫描,转换的
2、但是需要考虑的一个点:有可能我们注入的bean是ImportSelector或者ImportBeanDefinitionRegistrar的实现类,而ImportSelector所注入的类中,有可能还有ImportSelector或者是ImportBeanDefinitionRegistrar的实现类,所以,在源码中,会进行一个递归的判断,一直解析到当前bean是一个普普通通的bean,然后将所有的bean存到一个集合中
3、需要注意的是,这时候,通过@Import引入的ImportSelector和ImportBeanDefinitionRegistrar实现类中,返回的bean还是一个普通的class对象,并没有转换为beanDefinition,spring在解析完成之后,会统一对这两个实现类进行处理

4、所谓的统一处理,就是按照当前是importBeanDefinitionRegistrar还是ImportSelector,还是@Bean注入的,去处理,转换为beanDefinition,然后存入到beanDefinitionMap中

应用

接下来主要说应用,其实对于@Import注解,
1、我们可以直接通过@Import引入一个普通的bean
2、也可以引入一个ImportSelector的实现类
3、也可以引入一个ImportBeanDefinitionRegistrar的实现类

ImportBeanDefinitionRegistrar
@Configuration
@ComponentScan("com.spring.study.importbeandefinitionregistrar")
@Import({MyImportBeanDefinitionRegistrar.class,ImportTestBean.class})
public class ImportConfig {
}
public class ImportTestBean {
}
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        System.out.println("自己手动注入一个bean");
        BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(OrderBean.class);
        registry.registerBeanDefinition("orderBean", beanDefinitionBuilder.getBeanDefinition());
    }
}
public class OrderBean {
}
public class TestImportBeanDefinitionRegistrar {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(ImportConfig.class);
        System.out.println(ac.getBean(OrderBean.class));
        System.out.println(ac.getBean(ImportTestBean.class));
    }
}

最终的打印结果

自己手动注入一个bean
18:49:04.903 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerProcessor'
18:49:04.906 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerFactory'
18:49:04.907 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalAutowiredAnnotationProcessor'
18:49:04.909 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalCommonAnnotationProcessor'
18:49:04.927 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'importConfig'
18:49:04.936 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'com.spring.study.importbeandefinitionregistrar.ImportTestBean'
18:49:04.936 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'orderBean'
com.spring.study.importbeandefinitionregistrar.OrderBean@43301423
com.spring.study.importbeandefinitionregistrar.ImportTestBean@2f112965

这里的@Import注解注入了两个class,一个是普通的bean,一个是importBeanDefinitionRegistrar的实现类
所以,ImportBeanDefinitionRegistrar接口的作用就是将BeanDefinitionRegistry交给程序员,由程序员自己去决定要做的业务逻辑

ImportSelector
public class MyImportSelector implements ImportSelector {

    @Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        return new String[]{"com.spring.study.importselector.OperChannelEntity","com.spring.study.importselector.UserBean"};
    }
}

importSelector就不贴太多的代码了,只要把这个bean,通过@Import注解引入,spring就会帮我们注入OperChannelEntiry和UserBean这两个class

springboot的自动注入,就是用到了这个点,实现了ImportSelector,然后将要自动注入的bean,获取到其全类名,然后放入到返回的数组中即可

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值