前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring 中的 @Import 注解及向容器中添加 Bean 的几种方式

Spring 中的 @Import 注解及向容器中添加 Bean 的几种方式

作者头像
wsuo
发布2020-07-30 17:11:42
1.6K0
发布2020-07-30 17:11:42
举报
文章被收录于专栏:技术进阶之路技术进阶之路

这次介绍一下 Spring 中的一个重要的注解 @Import 以及向容器中添加 Bean 的几种方式 ,该注解在 SpringBoot 自动转配中起到重要的作用。

本文的组织结构如下:

  • 先看一下该注解有什么作用;
  • 再总览这个注解有哪些属性值;
  • 最后讲解一下重要的属性值。

Spring 版本 5.1.2.RELEASE

一、该注解的作用

先来回想一下我们将组件注册到容器中的几种方法:

  1. 使用 包扫描+注解标识,但是这种方式局限于自己写的类,第三方包一般不能修改;
  2. 使用 @Bean 注解,可以导入第三方包里面的组件,局限性是必须一个一个的导入,而且必须写一个方法;
  3. @Import 快速的给容器中导入组件:
    • @Import:容器中会自动注册该组件,id 默认是全类名;
    • ImportSelector:返回需要导入的组件的全类名数组,组件名为全类名;
    • ImportBeanDefinitionRegistrar:手动注册 Bean 到容器中,可以自定义组件名。
  4. 使用 Spring 提供的 FactoryBean (工厂 Bean 的方式)。

其中 @Bean 是自定义创建对象的方式,而包扫描和 @Import 是调用无参构造创建对象放入容器中,而 FactoryBean 是使用简单工厂模式,调用 get*** 方法获取对象。

可以在类上面直接加上这个注解 @Import(Color.class),容器中就会有 Color 这个类。

也可以同时导入多个类 @Import({Color.class, Red.class})

代码语言:javascript
复制
top.wsuo.bean.Color
top.wsuo.bean.Red

二、属性总览

该注解只接收类数组,只有一个属性 value:

代码语言:javascript
复制
Class<?>[] value();

我们可以直接传入类名,或者 ImportSelectorImportBeanDefinitionRegistrar 的实现类,这两个接口下面会详细介绍。

我们先在配置类中加上注解:

代码语言:javascript
复制
@Configuration
@Import({Color.class, Red.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
public class MainConfig2 {

其中 MyImportSelectorMyImportBeanDefinitionRegistrar 后面会介绍;

三、重要属性讲解

ImportSelector

ImportSelector 是一个接口,需要我们自己实现该类,需要实现一个方法叫做 selectImports

代码语言:javascript
复制
public class MyImportSelector implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[0];
    }
}

该方法有一个参数 AnnotationMetadata ,它可以获取到标注了 @Import 注解类的所有注释信息;

返回值就是要导入到容器中的组件的全类名。

代码语言:javascript
复制
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
    return new String[]{"top.wsuo.bean.Blue", "top.wsuo.bean.Yellow"};
}

这样的话容器中就有这几个类了:

代码语言:javascript
复制
top.wsuo.bean.Color
top.wsuo.bean.Red
top.wsuo.bean.Blue
top.wsuo.bean.Yellow

ImportBeanDefinitionRegistrar

它也是一个接口,需要自己写实现类,实现一个方法叫做 registerBeanDefinitions

这个方法有一个参数 BeanDefinitionRegistry ,他有一个方法 registerBeanDefinition ,可以自定义注册组件到容器中,第一个参数是自定义的组件名称,第二个参数是要求是 BeanDefinition 类型的,一般我们使用它的一个实现类 RootBeanDefinition 传入我们想导入的组件。

代码语言:javascript
复制
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {

    /**
     * @param importingClassMetadata 当前类的注解信息
     * @param registry               BeanDefinition 注册类: 调用它的 registerBeanDefinition 方法将需要添加到容器中的 Bean 手工注册进来;
     */
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        boolean hasRed = registry.containsBeanDefinition("top.wsuo.bean.Red");
        boolean hasBlue = registry.containsBeanDefinition("top.wsuo.bean.Blue");
        if (hasRed && hasBlue) {
            registry.registerBeanDefinition("rainBow", new RootBeanDefinition(RainBow.class));
        }
    }
}

这里的实例方法的逻辑是:先判断容器中有没有 RedBlue 类,如果都有就将 RainBow 注册到容器中。

四、FactoryBean 方式注册组件

之前提到过 FactoryBean 的方式注册组件,现在来详细的讲解一下,当然这种方式和 @Import 注解无关。

我们和之前一样也是写一个实现类来继承 Spring 提供的接口 FactoryBean

代码语言:javascript
复制
public class ColorFactoryBean implements FactoryBean<Color> {

    /**
     * 获取对象
     *
     * @return 返回类型
     * @throws Exception 异常
     */
    @Override
    public Color getObject() throws Exception {
        return new Color();
    }

    /**
     * 获取类型
     *
     * @return 返回类型
     */
    @Override
    public Class<?> getObjectType() {
        return Color.class;
    }

    /**
     * 控制是单例吗:
     * - 如果返回 true 表示是单实例
     * - 如果返回 false 表示是多实例
     */
    @Override
    public boolean isSingleton() {
        return false;
    }
}

需要重写 3 个方法,方法的含义注释标识出来了。

我们在使用的时候可以通过 @Bean 的方式注册进去,看起来注册的是 FactoryBean 对象,实际上是 Color 对象,也就是该接口指定的泛型。

如果想要获取工厂 Bean 本身,需要给 id 前面加一个 & 标识。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-07-12 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、该注解的作用
  • 二、属性总览
  • 三、重要属性讲解
    • ImportSelector
      • ImportBeanDefinitionRegistrar
      • 四、FactoryBean 方式注册组件
      相关产品与服务
      容器服务
      腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档