本文来说下关于@Import注解的几个问题

文章目录

  • 概述
  • 导入配置的三种类型
  • 源码解释
  • 测试例子
    • 导入普通类
    • 导入带有@Configuration的配置类
    • 通过ImportSelector 方式导入的类
    • 通过 ImportBeanDefinitionRegistrar 方式导入的类
  • 本文小结

概述

在平时看源码或者很多配置类上面都会出现@Import注解,功能就是和Spring XML 里面 的 一样. @Import注解是用来导入配置类或者一些需要前置加载的类.。


导入配置的三种类型

@Import支持 三种方式

  1. 带有@Configuration的配置类(4.2 版本之前只可以导入配置类,4.2版本之后 也可以导入 普通类)
  2. ImportSelector 的实现
  3. ImportBeanDefinitionRegistrar 的实现

这些用法或许只有一个目的,就是导入Bean。那为什么要这么麻烦,手动导入Bean呢,@ComponentScan不是可以自动扫描包注册Bean嘛?

其实这里的原因有两点:

  • @ComponentScan一般只会扫到自己项目中的Bean,第三方jar包中的@Bean扫不到。
  • @Import注解可以结合@Conditional注解使用,即条件导入,@Conditional在spring源码中也是大量用到,这个我后面会专题介绍。

源码解释

源码解释

/*** Indicates one or more {@link Configuration @Configuration} classes to import.* *功能类似XML 里面的 <import/> ,可以导入 @Configuration配置类,ImportSelector、* ImportBeanDefinitionRegistrar 的实现,4.2 版本之后可以导入普通类(类似AnnotationConfigApplicationContext#register* )* <p>Provides functionality equivalent to the {@code <import/>} element in Spring XML.* Allows for importing {@code @Configuration} classes, {@link ImportSelector} and* {@link ImportBeanDefinitionRegistrar} implementations, as well as regular component* classes (as of 4.2; analogous to {@link AnnotationConfigApplicationContext#register}).** 可以在类级别声明或作为元注释声明* <p>May be declared at the class level or as a meta-annotation.* 如需要引入XML或其他类型的文件,使用@ImportResource注解* <p>If XML or other non-{@code @Configuration} bean definition resources need to be* imported, use the {@link ImportResource @ImportResource} annotation instead.*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Import {/*** {@link Configuration}, {@link ImportSelector}, {@link ImportBeanDefinitionRegistrar}* or regular component classes to import.*/Class<?>[] value();}

测试例子

导入普通类

新建一个TestA

package cn.wideth.test;public class TestA {public void printName() {System.out.println("类名 :" + Thread.currentThread().getStackTrace()[1].getClassName());}
}

新建一个ImportConfig,在类上面加上@Configuration,加上@Configuration是为了能让Spring 扫描到这个类,并且直接通过@Import引入TestA类

package cn.wideth.test;import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;@Import({TestA.class})
@Configuration
public class ImportConfig {}

TestA 是一个普通的类,现在可以被@Autowired注释然后调用,就直接说明已经被Spring 注入并管理了,普通的类都是需要先实例化

package cn.wideth.test;import cn.wideth.PdaAndIpadApplication;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;@RunWith(SpringRunner.class)
@SpringBootTest(classes = PdaAndIpadApplication.class)
public class ImportAnnotationTest {@Autowiredprivate TestA testA;@Testpublic void TestA() {testA.printName();}
}

测试结果


导入带有@Configuration的配置类

新建TestB

package cn.wideth.test;import org.springframework.context.annotation.Configuration;@Configuration
public class TestB {public void printName() {System.out.println("类名 :" + Thread.currentThread().getStackTrace()[1].getClassName());}
}

在ImportConfig.class里面直接引入TestB

package cn.wideth.test;import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;@Import({TestB.class})
@Configuration
public class ImportConfig {}

测试结果 TestB.class 的类上面已经有了@Configuration注解,本身就会配spring扫到并实例,@import引入带有@Configuration的配置文件,是需要先实例这个配置文件再进行相关操作

package cn.wideth.test;import cn.wideth.PdaAndIpadApplication;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;@RunWith(SpringRunner.class)
@SpringBootTest(classes = PdaAndIpadApplication.class)
public class ImportAnnotationTest {@Autowiredprivate TestB testb;@Testpublic void TestB() {testb.printName();}
}

程序结果


通过ImportSelector 方式导入的类

新建TestC.class

package cn.wideth.test;public class TestC {public void printName() {System.out.println("类名 :" + Thread.currentThread().getStackTrace()[1].getClassName());}
}

新建SelfImportSelector.class 实现ImportSelector 接口,注入TestC.class

package cn.wideth.test;import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;public class SelfImportSelector implements ImportSelector {@Overridepublic String[] selectImports(AnnotationMetadata importingClassMetadata) {return new String[]{"cn.wideth.test.TestC"};}
}

ImportConfig上面引入SelfImportSelector.class

package cn.wideth.test;import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;@Import({SelfImportSelector.class})
@Configuration
public class ImportConfig {}

测试程序

package cn.wideth.test;import cn.wideth.PdaAndIpadApplication;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;@RunWith(SpringRunner.class)
@SpringBootTest(classes = PdaAndIpadApplication.class)
public class ImportAnnotationTest {@Autowiredprivate TestC testc;@Testpublic void TestC() {testc.printName();}
}

测试结果


通过 ImportBeanDefinitionRegistrar 方式导入的类

新建TestD.class

package cn.wideth.test;public class TestD {public void printName() {System.out.println("类名 :" + Thread.currentThread().getStackTrace()[1].getClassName());}
}

新建SelfImportBeanDefinitionRegistrar.class,实现接口ImportBeanDefinitionRegistrar,注入TestD.class

package cn.wideth.test;import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;public class SelfImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {@Overridepublic void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {RootBeanDefinition root = new RootBeanDefinition(TestD.class);registry.registerBeanDefinition("testd", root);}
}

ImportConfig类上加上导入SelfImportBeanDefinitionRegistrar.class

package cn.wideth.test;import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;@Import({SelfImportBeanDefinitionRegistrar.class})
@Configuration
public class ImportConfig {}

测试程序

package cn.wideth.test;import cn.wideth.PdaAndIpadApplication;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;@RunWith(SpringRunner.class)
@SpringBootTest(classes = PdaAndIpadApplication.class)
public class ImportAnnotationTest {@Autowiredprivate TestD testd;@Testpublic void testd() {testd.printName();}
}

测试结果


本文小结

本文详细介绍了@Import注解相关的知识与内容。

关于@Import注解的几个问题相关推荐

  1. Spring Boot 关于 @Import注解 —— 导入资源

    @Import 在应用中,有时没有把某个类注入到IOC容器中,但在运用的时候需要获取该类对应的bean,此时就需要用到@Import注解. 示例如下: 先创建两个类,不用注解注入到IOC容器中,在应用 ...

  2. @import注解使用

    今天主要从以下几方面来介绍一下@Import注解 @Import注解是什么 @Import的三种使用方式 1,@Import注解是什么 通过导入的方式实现把实例加入springIOC容器中 2,@Im ...

  3. Spring中@Import注解的作用和使用

    查看Import注解源码 作用: 1.声明一个bean 2. 导入@Configuration注解的配置类 3.导入ImportSelector的实现类 4.导入ImportBeanDefinitio ...

  4. idea去掉无用import类_@Import注解的魅力

    本篇主要介绍Spring注解@Import的魅力所在:它能让你高度自由的定义配置类装载规则与Bean注册逻辑.@Import是Spring体系中的一个比较重要的注解,下面让我们一起看看它都有哪些神奇的 ...

  5. 五、Spring中的@Import注解

    一.使用@Import注解导入组件 @Import注解的作用是给容器中导入组件,回顾下我们给容器中导入组件的方式,可以通过Spring的xm配置方式,可以通过注解,如@Component等,也可以通过 ...

  6. 通过@Import注解把类注入容器的四种方式

    文章目录 1. @Import导入的四种方式 2. 准备工作 ①:导入普通类ConfigA ②:导入`@Configuration`配置类ConfigB ③:导入`ImportSelector`的实现 ...

  7. java的 import注解_[java]一分钟学会spring注解之@Import注解

    今天主要从以下几方面来介绍一下@Import注解 @Import注解是什么 @Import的三种使用方式 1,@Import注解是什么 通过导入的方式实现把实例加入springIOC容器中 2,@Im ...

  8. spring注解之@Import注解的三种使用方式

    1.@Import注解须知 1.@Import只能用在类上 ,@Import通过快速导入的方式实现把实例加入spring的IOC容器中 2.加入IOC容器的方式有很多种,@Import注解就相对很牛皮 ...

  9. @Import注解使用及源码分析

    1.简介 在阅读spring源码的时候,当读到解析@configuration这个注解的时候,发现其中解析到一个很重要的注解叫做@Import,可能很多人没有听过,没有翻阅源码的时候也是不知所云,其实 ...

最新文章

  1. c++ vscode 第三方库_Windows平台配置VSCode的C/C++环境,超清晰
  2. css3效果: animate实现点点点loading动画效果(一)
  3. 关于git fetch 和git pull 的区别
  4. 学了这四招,你在Linux上观看Netflix视频不发愁
  5. 2019牛客暑期多校训练营(第七场)J A+B problem
  6. SQL 查找是否存在,别再 count 了,很耗费时间的!
  7. Mac远程连接Windows的远程桌面服务
  8. c++真的比java难吗_开课吧Java课程怎么样?开课吧的Java课程真的那么好吗?
  9. 英语介词at、in、on常见用法(时间、地点、方位)
  10. BZOJ3772精神污染
  11. SND: 项目发布时Owning ClassInfo is null for property: private问题原因排查与解决
  12. Opencv中使用ocl模块遇到的问题
  13. java捕鱼达人_java捕鱼达人游戏(源码)
  14. C51模拟PS2键盘(三)
  15. 高职计算机专业英语词汇,职高英语单词复习
  16. 北信源内网安全与补丁分发系统简单功能介绍
  17. 计算机语言与智能家居的关系,来谈谈“智能家居”与“家庭自动化”的区别
  18. python怎么安装scrapy_windows下安装python+scrapy
  19. VUE_关于Vue.use()详解
  20. 案例11-生产环境重大事故

热门文章

  1. CCNA2.0笔记_ACL
  2. 苏宁智慧家庭助跑智慧零售
  3. Bootstrap表格内容垂直水平居中
  4. [Mac入门]如何在Mac下显示Finder中的所有文件
  5. Selenium2+python自动化28-table定位
  6. Django之Model操作
  7. Spring Boot应用的打包和部署
  8. 自定义序列化和反序列化的java实现
  9. 《统一沟通-微软-实战》-3-部署-Exchange 2010-2-自定义安装
  10. 重构-改善既有代码的设计 (该书写于1999)培训之一