@mapperscan注解_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

欢迎扫码加关注:

ae540b540f6e97d615170f7519965810.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/502066.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

httphost设置socks_socks5代理使用和安装配置

Socks简介&#xff1a;详情可以百度&#xff0c;不过我猜你对那一大堆术语也会像我一样觉得无语&#xff0c;所以我觉得你可以简单理解为它可以比较完美代理http/ftp/smtp等多种协议的代理工具就行了。其中最具有典型例子的就是QQ的登录、foxmail的邮件、火狐的网页浏览都可以直…

百合数c语言360问答,《百合花》

满意答案fadess1d2013.02.26采纳率&#xff1a;51% 等级&#xff1a;12已帮助&#xff1a;7212人作者茹志娟&#xff0c;于1958年3月在《延安》上面发表。这篇小说具有清新俊逸的艺术风格。是她前期的代表作。她写这篇小说时&#xff0c;中那个是反右斗争扩大化&#xff0c;…

python 实现显著性检测_使用python轻松实现高大上的YOLOV4对象检测算法

YOLO系列对象检测算法&#xff0c;算是人工智能技术领域的一匹黑马&#xff0c;当开发者宣布不再为YOLO系列检测算法更新时&#xff0c;很多开发者瞬间失去了”精神食粮“。突然&#xff0c;当YOLOV4检测算法发布的时候&#xff0c;让很多开发者喜出望外。YOLOV4对象检测YOLOV4…

reactnative 获取定位_【React Native】定位获取经纬度,当前城市等地址信息

最近做React Native时&#xff0c;需要用到城市定位的功能&#xff0c;React Native中文网的定位部分中也提供了相应的方法。主要用到的方法有&#xff1a;这里只需要获取到经纬度&#xff0c;城市等信息&#xff0c;持续监听的函数就不需要了。这里使用 getCurrentPosition 方…

linux hash 算法,识别哈希算法类型hash-identifier

识别哈希算法类型hash-identifier是一款哈希算法识别工具。通过该工具&#xff0c;用户可以识别哈希值所使用的哈希算法。确定算法后&#xff0c;就可以采用对应的工具进行xx。执行该命令如下所示&#xff1a;rootdaxueba:~# hash-identifier输出信息如下所示&#xff1a;#####…

calendar获取本周一的日期_Java Calendar 获取本周周一和周日代码

Java Calendar 获取本周周一和周日代码/*** 得到本周周一** return yyyy-MM-dd*/public static String getMondayOfThisWeek() {Calendar c Calendar.getInstance();int day_of_week c.get(Calendar.DAY_OF_WEEK) - 1;if (day_of_week 0)day_of_week 7;c.add(Calendar.DATE…

android source镜像源_【转载】Celadon快速上路指南Part2:编译Celadon镜像

Celadon快速上路指南Part2&#xff1a;编译Celadon镜像From: 孙晓璐 AndroidIA Celadon 9/20一目了然 | Celadon 新手上路快速通道隆重揭晓 | 打开Celadon 的正确姿势上一期我们向您介绍了如何安装Celadon预编译镜像&#xff08;Celadon快速上路指南 Part1&#xff1a;安装Cela…

光学字符识别 android,基于Android的光学字符识别研究与实现

摘要&#xff1a;随着Android手机平台的普及和信息化进程的不断推进,利用手持设备高效地将文档信息录入已经成为一个亟需解决的问题,其关键技术光学字符识别在手机上的应用日益受到人们重视.本文所做工作正是针对这一问题而展开.本文设计的Android平台光学字符识别通过手机摄像…

适合程序员的耳机_为什么很多程序员工作时都戴耳机?

观点一&#xff1a;非诚勿扰&#xff0c;想静静。1、啥也没听&#xff0c;只是带着耳机而已。只是想告诉别人不要打扰我&#xff0c;选择性屏蔽一些讨厌的人说的话&#xff0c;不回答他。2、在听笑话或者有声小说。特别不想工作的时候会很认真地听&#xff0c;如果进入工作状态…

python中os模块_Python的武器库11:os模块

说到编程语言python&#xff0c;有一个著名的格言"余生太短&#xff0c;只用python"。如果要分析为什么会存在这么一句格言&#xff1f;python的语法并不简单&#xff0c;有复杂难懂的部分&#xff0c;之所以有这样一句格言&#xff0c;是因为python中有很多强大的模…

Android实现拍照并存储功能,Android实现拍照及图片显示效果

本文实例为大家分享了Android拍照及图片显示的具体代码&#xff0c;供大家参考&#xff0c;具体内容如下1、功能声明当应用需要使用相机、NFC等外设时&#xff0c;需要在AndroidManifest.xml中进行声明。这样&#xff0c;当设备缺少这些外设时&#xff0c;应用商店的安装程序可…

list redis 怎样做排行_redis实现商品销量排行榜

之前练习做过一个网上商城&#xff0c;采用SSM框架实现。该项目有一个商品排行榜模块没有实现&#xff0c;决定采用springbootdubboredis实现该模块。1.新建springboot项目。本项目的springboot版本号为:org.springframework.bootspring-boot-starter-parent2.1.6.RELEASE引入d…

大学计算机基础python学多久_基于Python 的“大学计算机基础”课程教学设计

基于Python 的“大学计算机基础”课程教学设计 日期&#xff1a;2018-04-11 04:32 摘要 培养非计算机专业大学生的计算思维能力&#xff0c;在“大学计算机基础”课程教学中引入程序设计内容已成各大高校的共识&#xff0c;但选择何种程序设计语言仍然观点不一。本文针对大一新…

android设计招式之美,6 - 设计模式与Android框架设计f

本教程由麦可网录制&#xff0c;共55节&#xff0c;主要介绍的内容有设计模式与Android框架设计、Android框架与应用类别的接合卡榫(Hook)函数、 Template Method模式等&#xff0c;本站提供部分教程在线学习&#xff0c;全套教程请下载观看。完整目录如下&#xff1a;1 - 设计…

treeselect只选了分支节点全选_vue Treeselect 树形下拉框:获取选中节点的ids和lables操作...

API: https://vue-treeselect.js.org/#events1.ids: 即value1.lable: 需要用到方法&#xff1a;select(node,instanceId) 和 deselect(node,instanceId)v-model"DRHA_EFaultModeTree_value":multiple"true":options"DRHA_EFaultModeTree_options"…

java 同步锁_死磕 java同步系列之自己动手写一个锁Lock

问题&#xff08;1&#xff09;自己动手写一个锁需要哪些知识&#xff1f;&#xff08;2&#xff09;自己动手写一个锁到底有多简单&#xff1f;&#xff08;3&#xff09;自己能不能写出来一个完美的锁&#xff1f;简介本篇文章的目标一是自己动手写一个锁&#xff0c;这个锁的…

linux ofstream open,浅谈linux性能调优之十一:内存分配管理

linux下内存分配的管理主要通过内核参数来控制&#xff1a;1.与容量相关的内存可调参数以下参数位于 proc 文件系统的 /proc/sys/vm/ 目录中。overcommit_memory &#xff1a;规定决定是否接受超大内存请求的条件。这个参数有三个可能的值&#xff1a;* 0 — 默认设置。内核执行…

click事件在什么时候出发_剖析setTimeout和click点击事件的触发顺序

下面是一段非常简单的JavaScript代码dianjisetTimeout(function () {alert(timer handler)}, 2000)function test () {document.addEventListener(click, function (e) {alert(click handler)}, false)var startTime new Date()while ((new Date()).getTime() - startTime <…

android里canvas视频帧,移动端用canvas截取视频封面,如何不截取第一帧,而是截取其它的帧?...

我在微信开发工具里截的图是可以的&#xff0c;但是在手机上截的图缺变成全透明的了。我猜是视频的第一帧的问题微信开发工具的截图手机的截图我的代码&#xff1a;JS&#xff1a;function captureImage(video) {var scale1var canvas document.createElement("canvas&qu…

python画正方形内切圆_python画出三角形外接圆和内切圆的方法

刚看了《最强大脑》中英对决&#xff0c;其中难度最大的项目需要选手先脑补泰森多边形&#xff0c;再找出完全相同的两个泰森多边形。在惊呆且感叹自身头脑愚笨的同时&#xff0c;不免手痒想要借助电脑弄个图出来看看&#xff0c;闲来无事吹吹牛也是极好的。 今天先来画画外接圆…