首先我们要明确:@Import 注解是 Spring 提供的。

然后我们看一下该注解的官方注释:

Indicates one or more component classes to import — typically @Configuration classes.

Provides functionality equivalent to the <import/> element in Spring XML. Allows for importing @Configuration classes, ImportSelector and ImportBeanDefinitionRegistrar implementations, as well as regular component classes (as of 4.2; analogous to AnnotationConfigApplicationContext.register).

@Bean definitions declared in imported @Configuration classes should be accessed by using @Autowired injection. Either the bean itself can be autowired, or the configuration class instance declaring the bean can be autowired. The latter approach allows for explicit, IDE-friendly navigation between @Configuration class methods.

May be declared at the class level or as a meta-annotation.

If XML or other non-@Configuration bean definition resources need to be imported, use the @ImportResource annotation instead.

我们将其中我们关心的重要部分提取出来翻译整理如下:

  • 该注解可导入一个或多个组件类——通常是Configuration类。

  • 允许导入@Configuration类、ImportSelector接口和ImportBeanDefinitionRegistrar接口的实现,以及普通类(从4.2版本开始)。

  • @Import注解可以在类上声明,也可以作为元注解声明在其他注解上。

那么 @Import 注解到底有什么作用和优势呢?

记住下面几句话:

导入配置。

从各个地方、通过各种方式导入配置。

在你需要的时候,从各个地方、通过各种方式导入配置。

在你需要的时候,从各个地方、通过各种方式导入并改造成你喜欢的配置。


下面我们通过示例讲 4 种官方注释给出的导入类型,分别是:

  • 普通类

  • @Configuration类

  • ImportSelector接口实现

  • ImportBeanDefinitionRegistrar接口实现

普通类

普通类不必啰嗦,有手就行。

public class Circle {
}
@Configuration
@Import({Circle.class})
public class MainConfig {
}

导入@Configuration类

我们建立三个不同的模块,MainModule, Module1, Module2。

让 MainModule 引入 Module1、Module2依赖。

在 MainModule 中创建 MainConfig 类如下:

@Configuration
@Import({Config1.class, Config2.class})
public class MainConfig {
}

很明显,Config1,Config2 分别属于2个模块,如下:

@Configuration
public class Config1 {
    @Bean
    public String config1() {
        return "我是config1配置类!";
    }
}
@Configuration
public class Config2 {
    @Bean
    public String config2() {
        return "我是config2配置类!";
    }
}

在 MainModule 中创建测试类看是否生效:

@Test
void contextLoads() {
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
    for (String name : context.getBeanDefinitionNames()) {
        System.out.println(String.format("%s->%s", name, context.getBean(name)));
    }
}

测试结果如下:

mainConfig->com.example.annotation.config.MainConfig$$EnhancerBySpringCGLIB$$a98d5b6a@55a609dd
com.example.module1.config1->com.example.module1.config.Config1$$EnhancerBySpringCGLIB$$72aca5d0@4afd21c6
config1->我是config1配置类!
com.example.module2.config2->com.example.module2.config.Config2$$EnhancerBySpringCGLIB$$72aca5d0@4afd21c6
config2->我是config2配置类!

ImportSelector接口实现

首先我们需要认识一下 ImportSelector 接口:

public interface ImportSelector {

    String[] selectImports(AnnotationMetadata importingClassMetadata);

    @Nullable
    default Predicate<String> getExclusionFilter() {
        return null;
    }
}

只有一个需要实现的方法:

selectImports

参数 AnnotationMetadata 是什么?

翻译为注解元数据。

有什么用?

用来获取被@Import标注的类上面所有的注解信息。

String[] 是什么?

返回需要导入的类名的数组,可以是任何普通类,配置类。

上示例:

创建一个配置类

@Configuration
public class Config {
    @Bean
    public String name() {
        return "公众号:JavaCode";
    }
}

定义一个ImportSelectors实现类

public class MyImportSelector implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[]{
                Config.class.getName()
        };
    }
}

上述代码中需要说明一下,Config.class.getName() 得到的是类的全类名,也就是[包名.类名],也就是com.example.annotation.pojo.Config。

导入MyImportSelector

@Import({MyImportSelector.class})
public class MainConfig {
}

这时候有人问了:

这里怎么没有 @Configuration 注解?

没关系哈,虽然 @Import 注解通常是与 @Configuration 注解一起使用的,但不是绝对必要的。

ImportBeanDefinitionRegistrar接口实现

首先我们还是先认识一下 ImportBeanDefinitionRegistrar 接口:

public interface ImportBeanDefinitionRegistrar {

    default void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry, BeanNameGenerator importBeanNameGenerator) {
        registerBeanDefinitions(importingClassMetadata, registry);
    }
    default void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
    }
}

可以看到只有2个方法,第一个方法调用第二个方法,所以我们就只看第二个方法就好了。

AnnotationMetadata 我们前边说过了:

用来获取被@Import标注的类上面所有的注解信息。

BeanDefinitionRegistry 呢?

它是一个接口,内部提供了注册bean的各种方法,用于我们手动注册bean。

上示例:

创建一个 Java 类

public class Rectangle {
    public void sayHi() {
        System.out.println("Rectangle sayHi()");
    }
}

创建 ImportBeanDefinitionRegistrar 实现类

public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(Rectangle.class);
        // 注册一个名字叫做 rectangle 的 bean
        registry.registerBeanDefinition("rectangle", rootBeanDefinition);
    }
}

总结

第一种:

我们有什么就可以导什么。

第二种:

我们可以把分散的配置集中起来,更加清晰和有组织。

第三种:

除了我们模块现有的配置,你只要能拿到类的全类名,就能注册进来。

第四种:

我们不光能到处拿,我们还能拿来以后随便改!

以上四种方式就实现了我们当初的豪言:

导入配置。

从各个地方、通过各种方式导入配置。

在你需要的时候,从各个地方、通过各种方式导入配置。

在你需要的时候,从各个地方、通过各种方式导入并改造成你喜欢的配置。


● 终于搞懂动态代理了!

● 学会@ConfigurationProperties月薪过三千

● 学一点关于JVM类加载的知识

● Java注解,看完就会用

● Java反射,看完就会用

● @Value是个什么东西

不是银趴~是@Import!的更多相关文章

  1. [Python设计模式] 第2章 商场收银软件——策略模式

    github地址: https://github.com/cheesezh/python_design_patterns 题目 设计一个控制台程序, 模拟商场收银软件,根据客户购买商品的单价和数量,计 ...

  2. 金三银四求职季,前端面试题小梳理(HTML、CSS、JS)

    好久没写学习记录,最近太多事,又到一年求职季,都说金三银四求职季,自己也做一下最近学习的一些前端面试题梳理,还是个小白,写的不对请指正,不胜感激. HTML篇 html语义化 用语义化的代码标签书写, ...

  3. 一个excel(20M)就能干趴你的poi,你信吗?

    自从上一篇:一个普通类就能干趴你的springboot,你信吗?后,很巧的是这次又发现一个问题,所以有了这篇文章,还是想沿用上篇的”流水帐“的方式查找问题和解决问题.这篇文章主要是因为使用POI导入一 ...

  4. 金三银四,磨砺锋芒;剑指大厂,扬帆起航(2020年最全大厂WEB前端面试题精选)上

    金三银四,磨砺锋芒:剑指大厂,扬帆起航(2020年最全大厂WEB前端面试题精选)上 引言 元旦匆匆而过,2020年的春节又接踵而来,大家除了忙的提着裤子加班.年底冲冲冲外,还有着对于明年的迷茫和期待! ...

  5. 金三银四科学找工作,用python大数据分析一线城市1000多份岗位招聘需求

    文章每周持续更新,各位的「三连」是对我最大的肯定.可以微信搜索公众号「 后端技术学堂 」第一时间阅读(一般比博客早更新一到两篇) 每年的三四月份是招聘高峰,也常被大家称为金三银四黄金招聘期,这时候上一 ...

  6. 备战金三银四!一线互联网公司java岗面试题整理:Java基础+多线程+集合+JVM合集!

    前言 回首来看2020年,真的是印象中过的最快的一年了,真的是时间过的飞快,还没反应过来年就夸完了,相信大家也已经开始上班了!俗话说新年新气象,马上就要到了一年之中最重要的金三银四,之前一直有粉丝要求 ...

  7. ES6模块import细节

    写在前面,目前浏览器对ES6的import支持还不是很好,需要用bable转译. ES6引入外部模块分两种情况: 1.导入外部的变量或函数等: import {firstName, lastName, ...

  8. spring源码分析之@ImportSelector、@Import、ImportResource工作原理分析

    1. @importSelector定义: /** * Interface to be implemented by types that determine which @{@link Config ...

  9. Python标准模块--import

    1 模块简介 作为一个Python初学者,你首先要学会的知识就是如何引入其它模块或者包.但是,我发现有些开发者虽然使用Python很多年,依然不了解Python引入机制的灵活性.这篇文章,我们就会研究 ...

  10. css和@import区别用法

    css和@import都是调用外部样式表的方法. 一.用法 (1)link: <link rel="stylesheet" type="text/css" ...

随机推荐

  1. Springboot 实现QQ登录(界面跳转)

    Springboot 实现QQ登录(界面跳转) 现在第三方登录已经变成主流app的登录方式了 今天记录一下如何给自己的网站实现第三方登录(这里以QQ登录为例) 准备工作 首先确保你准备好你自己网站的域 ...

  2. C语言条件运算符(?:)

    条件运算符(conditional operator)有时候也称为三元运算符(ternary operator,或者trinary operator),因为它是唯一需要 3 个操作数的运算符: 条件 ...

  3. FFMPEG+SDL简单视频播放器——人脸检测

    前言 最近突发奇想,给播放器加上一个人脸检测的功能(事情似乎朝着奇怪的方向发展了,谁家的播放器会需要去检测人脸啊!),主要的目的是为了学习opencv,尝试将ffmpeg和opencv融合在一起使用. ...

  4. 创建vue项目并搭建JSONSERVER

    1.该前提是你已经搭建好vue-cli脚手架,开始创建一个新项目,输入 vue init webpack demo(demo是自定义项目名). 2.cd demo 进入项目安装依赖 3.在已经创建的项 ...

  5. Windows下音视频对讲演示程序(声学回音消除、噪音抑制、语音活动检测、自动增益控制、自适应抖动缓冲)(2023年07月13日更新)

    Windows下音视频对讲演示程序 必读说明 简介   本软件根据<道德经>为核心思想而设计,实现了两个设备之间进行音视频对讲,一般可用于楼宇对讲.智能门铃对讲.企业员工对讲.智能对讲机. ...

  6. js执行过程之上下文对象(Context)

    在js的学习中,我们已经不满足于仅了解js的基础知识,而是开始追求更深层次的学习.因为你会发现,仅了解js的基础知识,在开发项目的过程中是远远不够的.今天就来介绍一下在js执行过程中的一些相关内容了. ...

  7. 一款.NET开源的小巧、智能、免费的Windows内存清理工具 - WinMemoryCleaner

    前言 我们在使用Windows系统的时候经常会遇到一些程序不会释放已分配的内存,从而导致电脑变得缓慢.今天给大家推荐一款.NET开源的小巧.智能.免费的Windows内存清理工具:WinMemoryC ...

  8. Java核心知识体系7:线程安全性讨论

    Java核心知识体系1:泛型机制详解 Java核心知识体系2:注解机制详解 Java核心知识体系3:异常机制详解 Java核心知识体系4:AOP原理和切面应用 Java核心知识体系5:反射机制详解 J ...

  9. VCS用法

    1.时钟频率点击,鼠标左键点击波形上升沿,中间滚轮点击,然后选择hz,就显示当前信号时钟频率. 2.窗口乱掉,找不到文件列表,右下角点击弹出选择instance. 3.bus地址查找,选择信号,然后蓝 ...

  10. .NET微信网页开发之网页授权获取用户基本信息

    开发背景 当用户在微信客户端中访问第三方网页,公众号可以通过微信网页授权机制,来获取用户基本信息,进而实现业务逻辑.我们一般通过用户网页授权来无感实现用户登录,并获取用户的微信信息. 注意:用户管理类 ...