ideal如何快速导入import_Spring的@Import注解详解
首先看下@Import的javadoc文档:
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.
简单翻译一下,这里面说了3个点:
(1)@Import就是用来向容器中导入bean的,导入的方式有三种:导入@Configuration、导入ImportSelector、导入ImportBeanDefinitionRegistrar。
(2)被@Import的类是被加载到了Spring容器当中,因此无论是类本身还是类里面用@Bean注解定义的bean都可以被@Autowired注入。
(3)@Import可以加在类上面,也可以作为元注解加在注解上面
下面就来分别举例说明下。
1.导入@Configuration举例
//这是个普通的类
public class Service1 {public Service1(){System.out.println("Service1");}
}
//这是个配置类
@Configuration
public class DemoConfig {@Beanpublic Service2 service2(){return new Service2();}
}
@SpringBootApplication
//这样可以导入Service1和Service2这两个Bean
@Import({Service1.class, DemoConfig.class})
public class ImportDemoApplication {public static void main(String[] args) {SpringApplication.run(ImportDemoApplication.class, args);}
}
2.导入ImportSelector举例
public class DemoImportSelector implements ImportSelector {@Overridepublic String[] selectImports(AnnotationMetadata importingClassMetadata) {//这里返回bean的完整的名字return new String[]{"com.github.xjs.importdemo.service.Service3"};}
}
@SpringBootApplication
//这样就可以导入Service3这个bean
@Import({DemoImportSelector.class})
public class ImportDemoApplication {public static void main(String[] args) {SpringApplication.run(ImportDemoApplication.class, args);}
}
3.导入ImportBeanDefinitionRegistrar举例
public class DemoRegistrar implements ImportBeanDefinitionRegistrar {@Overridepublic void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {//可以直接向容器注册beanGenericBeanDefinition bd = new GenericBeanDefinition();bd.setBeanClass(Service4.class);registry.registerBeanDefinition("service4", bd);}
}
@SpringBootApplication
//这样就可以导入Service4这个bean
@Import({DemoRegistrar.class})
public class ImportDemoApplication {public static void main(String[] args) {SpringApplication.run(ImportDemoApplication.class, args);}
}
4.@Import作为元注解使用举例
因为@Import可以作为元注解使用,因此可以用这个特性来做组件扫描,比如:
//首先定义一个用于扫描的注解,上面添加@Import元注解:
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Import({DemoImportSelector.class})
public @interface DemoScan {/*** 要扫描的根路径* */String basePackage() default "";
}
然后在启动类或者配置类上添加这个注解:
@SpringBootApplication
//首先添加这个注解
@DemoScan(basePackage="com.github.xjs")
@Import({DemoImportSelector.class, DemoRegistrar.class})
public class ImportDemoApplication {public static void main(String[] args) {SpringApplication.run(ImportDemoApplication.class, args);}
}
无论是ImportSelector还是ImportBeanDefinitionRegistrar在回调中都可以使用AnnotationMetadata获取@DemoScan里面的属性:
public class DemoImportSelector implements ImportSelector {@Overridepublic String[] selectImports(AnnotationMetadata importingClassMetadata) {//读取DemoScan的属性AnnotationAttributes annoAttrs = AnnotationAttributes.fromMap(importingClassMetadata.getAnnotationAttributes(DemoScan.class.getName()));String basePackage = annoAttrs.getString("basePackage");System.out.println("basePackage:"+basePackage);return new String[]{"com.github.xjs.importdemo.service.Service3"};}
}
拿到了要扫描的路径如何去扫描可以参考上一篇如何去扫描Mapper接口的,在Spring的源码中有大量的这种用法,比如:ServletComponentScan与ServletComponentScanRegistrar、MapperScan与MapperScannerRegistrar等等。
5.@Import解析的源码
// org.springframework.context.annotation.ConfigurationClassParser:
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,Collection<SourceClass> importCandidates, boolean checkForCircularImports) {...for (SourceClass candidate : importCandidates) {if (candidate.isAssignable(ImportSelector.class)) {// Candidate class is an ImportSelector -> delegate to it to determine importsClass<?> candidateClass = candidate.loadClass();ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class);ParserStrategyUtils.invokeAwareMethods(selector, this.environment, this.resourceLoader, this.registry);if (selector instanceof DeferredImportSelector) {this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);}else {String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames);processImports(configClass, currentSourceClass, importSourceClasses, false);}}else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {// Candidate class is an ImportBeanDefinitionRegistrar ->// delegate to it to register additional bean definitionsClass<?> candidateClass = candidate.loadClass();ImportBeanDefinitionRegistrar registrar = BeanUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class);ParserStrategyUtils.invokeAwareMethods(registrar, this.environment, this.resourceLoader, this.registry);configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());}else {// Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->// process it as an @Configuration classthis.importStack.registerImport(currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());processConfigurationClass(candidate.asConfigClass(configClass));}}...
}
}
完整的源码下载:
https://github.com/xjs1919/enumdemo 下的 import-demo
欢迎扫码加关注:
ideal如何快速导入import_Spring的@Import注解详解相关推荐
- 【Spring】@Import注解详解
简述 @Import注解import的是其他地方定义的Bean,将松散的Bean集合在一起. 既可以引入普通类作为Bean,又可以引入标记了@Configuration类中的所有Bean. 1. 引入 ...
- @Import注解详解
@Import注解提供了三种用法 1.@Import一个普通类 spring会将该类加载到spring容器中 2.@Import一个类,该类实现了ImportBeanDefinitionRegistr ...
- @mapperscan注解_Spring的@Import注解详解
首先看下@Import的javadoc文档: Provides functionality equivalent to the <import/> element in Spring XM ...
- php 如何封装类库,ThinkPHP里的import方法用于类库导入的封装实现实例详解
ThinkPHP里的import方法用于类库导入的封装实现实例详解 分类:PHP_Python| 发布:佚名| 查看: | 发表时间:2014/7/1 import方法是ThinkPHP框架用于类库导 ...
- springioc注解详解
springioc注解详解 文章目录 springioc注解详解 *简略核心解释 一.springioc是什么? 二.使用步骤 1.使用注解的方式注册bean到IOC容器中 2.使用@AutoWire ...
- JDBC学习笔记01【JDBC快速入门、JDBC各个类详解、JDBC之CRUD练习】
黑马程序员-JDBC文档(腾讯微云)JDBC笔记.pdf:https://share.weiyun.com/Kxy7LmRm JDBC学习笔记01[JDBC快速入门.JDBC各个类详解.JDBC之CR ...
- Spring零配置之@Configuration注解详解
转载自 Spring零配置之@Configuration注解详解 @Configuration介绍 Spring3.0之前要使用Spring必须要有一个xml配置文件,这也是Spring的核心文件,而 ...
- Spring Boot注解详解
文章目录 使用注解的优势 注解详解(配备了完善的释义) 注解列表如下 JPA注解 springMVC相关注解 全局异常处理 项目中具体配置解析和使用环境 使用注解的优势 采用纯java代码,不在需要配 ...
- 【SpringBoot 】SpringBoot注解详解
[SpringBoot ]SpringBoot注解详解 一.注解(annotations)列表 @SpringBootApplication:包含了@ComponentScan.@Configura ...
最新文章
- ASA IPSEC ***配置
- 一块网卡绑定多个ip
- c语言指针字符串逆序存放,C语言指针实现字符串的反转
- 2021 icme_重磅 | 2021年U.S. News 全美院校排名发布,疫情之下,排名大洗牌?!
- 网络编程知识预备(5) ——libcurl库简介及其编程访问百度首页
- [数据结构]链表中销毁和清空的区别
- LeetCode 211. 添加与搜索单词 - 数据结构设计(Trie树)
- Java面试通关要点汇总集答案(七)——equals 与 == 的区别 List 和 Set 区别
- mycat分表之ER表分片、范围分片、取模分片、日期分片、全局表等
- CACTI 仙人掌监控平台
- yolov5鱼苗检测计数:从数据标注到训练
- 《51单片机应用开发从入门到精通》——1.3 Keil uVision2集成开发环境
- Java开发从零开始!java游戏服务器开发教程
- rust炼油机怎么搞_rust挖油机在哪个位置 | 手游网游页游攻略大全
- 51nod 1108.距离之和最小 V2 - 曼哈顿距离
- 千万级规模高性能、高并发的网络架构经验分享
- JZOJ 5207【GDOI2018模拟7.7】暴力大神hxx
- 我的编程之路:从好玩到玩好
- [再寄小读者之数学篇](2014-11-20 计算二重积分)
- node中全局对象一 --- __dirname和__filename
热门文章
- 【分享】Vue 资源典藏(UI组件、开发框架、服务端、辅助工具、应用实例、Demo示例)...
- bootstrap layui 两种分页的实现
- Linux线程-互斥锁pthread_mutex_t
- Java内存溢出详解
- 【集合框架】JDK1.8源码分析之IdentityHashMap(四)
- PyQt的Layout的比例化分块。
- oracle监听器启动错误-TNS-12546: TNS:permission denied
- Linux硬盘安装_ubuntu
- HTML5 特性检测:Canvas(画布)
- python3 nmap 函数简介