揭密springboot自动装配(1)--ImportSelector

2024-06-04 19:18

本文主要是介绍揭密springboot自动装配(1)--ImportSelector,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

揭密springboot自动装配

  1. 揭密springboot自动装配(1)--ImportSelector
  2. 揭密springboot自动装配(2)--AutoConfigurationImportSelector
  3. 揭密springboot自动装配(3)--ioc及调用selectImposts
  4. 揭密springboot自动装配(4)--ioc及创建beanFactory
  5. 揭密springboot自动装配(5)--ioc及@Autowired注解

在讲这个之前,我们先来个例子热热身


首先我们先来了解下ImportSelector这个接口的应用,ImportSelector接口是spring中导入外部配置的核心接口,在SpringBoot的自动化配置和@EnableXXX(功能性注解)都有它的存在,具体怎么用下面走个例子看看

1.实现下ImportSelector

public class UserImportSelector implements ImportSelector {@Overridepublic String[] selectImports(AnnotationMetadata annotationMetadata) {return new String[]{UserA.class.getName()};}
}

这里我们看到有个selectImports方法,我们需要实现它,返回内容我们可以看到就是个数组,把需要装配进spring容器中的bean的className放进返回数组即可

2.接着我们在启动类中添加@Import(UserImportSelector.class)

@SpringBootApplication
@Import(UserImportSelector.class)
public class DemoApplication {public static void main(String[] args) {ConfigurableApplicationContext run = SpringApplication.run(DemoApplication.class, args);Object userA = run.getBeanFactory().getBean(UserA.class);System.out.println(userA.toString());Object userB = run.getBeanFactory().getBean(UserB.class);System.out.println(userB.toString());}}

这里UserB我是没有放在selectImports中的,目的是做下对比

3.跑下我们的程序看看结果

这里你会发现UserA可以被拿到,证明已经交给spring容器中可以拿到,而UserB我没有任何处理,是拿不到的这个毫无疑问到这里肯定有人会问,直接@Import(UserA.class)不就行了,搞那么复杂,嗯,这个没错,甚至我可以跑给你们看下

@SpringBootApplication
@Import({UserImportSelector.class,UserB.class})
public class DemoApplication {public static void main(String[] args) {ConfigurableApplicationContext run = SpringApplication.run(DemoApplication.class, args);Object userA = run.getBeanFactory().getBean(UserA.class);System.out.println(userA.toString());Object userB = run.getBeanFactory().getBean(UserB.class);System.out.println(userB.toString());}}

那为什么搞那么复杂?

ImportSelector主要是实现些比较复杂有逻辑性的bean装载,我们可以在selectImports做下逻辑判断,比如@ComponentScan像这个扫描器,我们自己来写一个和它差不多的东西玩玩,起名@UserScan

1.创建注解@UserScan,引用@Import(UserImportSelector.class)

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Import(UserImportSelector.class)
public @interface UserScan {@AliasFor("basePackages")String[] value() default {};@AliasFor("value")String[] basePackages() default {};
}

2.实现UserImportSelector 

public class UserImportSelector implements ImportSelector {@Overridepublic String[] selectImports(AnnotationMetadata annotationMetadata) {Map<String, Object> annotationAttributes = annotationMetadata.getAnnotationAttributes(UserScan.class.getName());if(CollectionUtils.isEmpty(annotationAttributes))return new String[0];String[] basePackages = (String[]) annotationAttributes.get("basePackages");ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false);scanner.addIncludeFilter(new AssignableTypeFilter(Object.class));//这里实现包含,相当@ComponentScan  includeFilters//scanner.addExcludeFilter(new AssignableTypeFilter(Object.class));//这里可以实现排除,相当@ComponentScan  excludeFiltersSet<String> classes = new HashSet<>();for (String basePackage : basePackages) {Set<BeanDefinition> candidateComponents = scanner.findCandidateComponents(basePackage);candidateComponents.forEach(e-> {classes.add(e.getBeanClassName());});}return classes.toArray(new String[classes.size()]);//return new String[]{UserA.class.getName()};}
}

3.使用@UserScan("com.example.demo.service"),表示扫描包下的类

@SpringBootApplication
@UserScan("com.example.demo.service")
public class DemoApplication {public static void main(String[] args) {ConfigurableApplicationContext run = SpringApplication.run(DemoApplication.class, args);Object userA = run.getBeanFactory().getBean(UserA.class);System.out.println(userA.toString());Object userB = run.getBeanFactory().getBean(UserB.class);System.out.println(userB.toString());}
}

4.我们跑起来看看结果

这样可以看到我们是完全可以在spring容器里面拿到UserA和UserB的

好了,热身例子到这里下文将会从源码上分析springboot自动装载的实现,主要和我们前面讲的ImportSelector接口有关,其中有个叫做AutoConfigurationImportSelector的东西,下文将会提到

这篇关于揭密springboot自动装配(1)--ImportSelector的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1030884

相关文章

微信公众号脚本-获取热搜自动新建草稿并发布文章

《微信公众号脚本-获取热搜自动新建草稿并发布文章》本来想写一个自动化发布微信公众号的小绿书的脚本,但是微信公众号官网没有小绿书的接口,那就写一个获取热搜微信普通文章的脚本吧,:本文主要介绍微信公众... 目录介绍思路前期准备环境要求获取接口token获取热搜获取热搜数据下载热搜图片给图片加上标题文字上传图片

Java编译生成多个.class文件的原理和作用

《Java编译生成多个.class文件的原理和作用》作为一名经验丰富的开发者,在Java项目中执行编译后,可能会发现一个.java源文件有时会产生多个.class文件,从技术实现层面详细剖析这一现象... 目录一、内部类机制与.class文件生成成员内部类(常规内部类)局部内部类(方法内部类)匿名内部类二、

SpringBoot实现数据库读写分离的3种方法小结

《SpringBoot实现数据库读写分离的3种方法小结》为了提高系统的读写性能和可用性,读写分离是一种经典的数据库架构模式,在SpringBoot应用中,有多种方式可以实现数据库读写分离,本文将介绍三... 目录一、数据库读写分离概述二、方案一:基于AbstractRoutingDataSource实现动态

Springboot @Autowired和@Resource的区别解析

《Springboot@Autowired和@Resource的区别解析》@Resource是JDK提供的注解,只是Spring在实现上提供了这个注解的功能支持,本文给大家介绍Springboot@... 目录【一】定义【1】@Autowired【2】@Resource【二】区别【1】包含的属性不同【2】@

springboot循环依赖问题案例代码及解决办法

《springboot循环依赖问题案例代码及解决办法》在SpringBoot中,如果两个或多个Bean之间存在循环依赖(即BeanA依赖BeanB,而BeanB又依赖BeanA),会导致Spring的... 目录1. 什么是循环依赖?2. 循环依赖的场景案例3. 解决循环依赖的常见方法方法 1:使用 @La

Java枚举类实现Key-Value映射的多种实现方式

《Java枚举类实现Key-Value映射的多种实现方式》在Java开发中,枚举(Enum)是一种特殊的类,本文将详细介绍Java枚举类实现key-value映射的多种方式,有需要的小伙伴可以根据需要... 目录前言一、基础实现方式1.1 为枚举添加属性和构造方法二、http://www.cppcns.co

Elasticsearch 在 Java 中的使用教程

《Elasticsearch在Java中的使用教程》Elasticsearch是一个分布式搜索和分析引擎,基于ApacheLucene构建,能够实现实时数据的存储、搜索、和分析,它广泛应用于全文... 目录1. Elasticsearch 简介2. 环境准备2.1 安装 Elasticsearch2.2 J

Java中的String.valueOf()和toString()方法区别小结

《Java中的String.valueOf()和toString()方法区别小结》字符串操作是开发者日常编程任务中不可或缺的一部分,转换为字符串是一种常见需求,其中最常见的就是String.value... 目录String.valueOf()方法方法定义方法实现使用示例使用场景toString()方法方法

Java中List的contains()方法的使用小结

《Java中List的contains()方法的使用小结》List的contains()方法用于检查列表中是否包含指定的元素,借助equals()方法进行判断,下面就来介绍Java中List的c... 目录详细展开1. 方法签名2. 工作原理3. 使用示例4. 注意事项总结结论:List 的 contain

Java实现文件图片的预览和下载功能

《Java实现文件图片的预览和下载功能》这篇文章主要为大家详细介绍了如何使用Java实现文件图片的预览和下载功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... Java实现文件(图片)的预览和下载 @ApiOperation("访问文件") @GetMapping("