@Import导入自定义选择器

之前一篇博文:Spring中的@Import注解已经详细介绍了@Import注解,不赘述。

需求描述

通过@import注解自定义组件选择器,将满足我们自定义的规则的bean导入到ioc容器中

项目结构

案例代码

首先是UserService接口及其实现类

public interface UserService {
void saveUser();
} // 注意这里我们没有加入@service注解,因为我们将不采用@componentScan去指定扫描的注解。
public class UserServiceImpl implements UserService { @Override
public void saveUser() {
System.out.println("保存用户");
}
}

配置类:

@Configuration
@ComponentScan("com.helius")
@Import(CustomeImportSelector.class)
public class SpringConfiguration { }

这里必须明确:尽管我们在配置上类加了@ComponentScan注解,但是@ComponentScan默认的扫描规则是扫描指定包下的@Service、@Component、@Repository、@Controller

但是这里我们在com.helius包下的类上没有加这些注解


自定义类型选择器

package importselect;

import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.io.support.PropertiesLoaderUtils;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.filter.AspectJTypeFilter;
import org.springframework.core.type.filter.TypeFilter; import java.io.IOException;
import java.util.HashSet;
import java.util.Map;
import java.util.Properties;
import java.util.Set; /**
* //返回值,就是到导入到容器中的组件全类名
* //AnnotationMetadata:当前标注@Import注解的类的所有注解信息
* 自定义导入器
*
* @Author Helius
* @Create 2019-10-31-20:11
*/
public class CustomeImportSelector implements ImportSelector {
/**
* 实现获取要导入类的字节码
* 需求:导入的过滤规则TypeFilter采用aspectj表达式的方式
*/
//表达式(ASPECTJ表达式)
private String expression; /**
* 默认构造函数
* 用于读取配置文件,给表达式赋值
*/
public CustomeImportSelector() {
try {
/* InputStream resourceAsStream = CustomeImportSelector.class.getResourceAsStream("/customeimport.properties");
Properties properties = new Properties();
properties.load(resourceAsStream);*/ //1.获取properties对象
Properties properties =
PropertiesLoaderUtils.loadAllProperties("customeimport.properties");
//2.给expression赋值
expression = properties.getProperty("custome.importselector.expression");
} catch (IOException e) {
e.printStackTrace();
}
} @Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
//1.定义扫描包的名称
String[] basePackages = null;
//2.判断有@Improt注解的类上是否有@ComponentScan注解
if (importingClassMetadata.hasAnnotation(ComponentScan.class.getName())) {
//3.取出@ComponentScan注解的属性(basePackages/value)
Map<String, Object> annotationAttributes =
importingClassMetadata.getAnnotationAttributes(ComponentScan.class.getName());
//4.取出属性名称为basePackages属性的值
basePackages = (String[]) annotationAttributes.get("basePackages");
}
//5.判断是否有此属性(如果没有ComponentScan注解则属性值为null,如果有 ComponentScan注解,则basePackages默认为空数组)
if (basePackages == null || basePackages.length == 0) {
String basePackage = null;
try {
// 6.取出包含@import注解的类所在包的名称
basePackage = Class.forName(importingClassMetadata.getClassName()).getPackage().getName();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//7.存入数组中
basePackages = new String[]{basePackage};
}
//8.创建类路径扫描器 参数的含义:表明不使用默认过滤规则
ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false);
//9.创建类型过滤器(此处使用AspectJ表示式类型过滤器)
TypeFilter typeFilter = new AspectJTypeFilter(expression,CustomeImportSelector.class.getClassLoader());
//10.把类型过滤器添加到扫描器中
scanner.addIncludeFilter(typeFilter);
//11.定义要扫描类的全限定类名集合
Set<String> classes = new HashSet<>();
//12.填充集合的内容
for (String basePackage : basePackages) {
scanner.findCandidateComponents(basePackage).forEach(beanDefinition -> classes.add(beanDefinition.getBeanClassName()));
}
//13.按照方法的返回值要求,返回全限定类名的数组
return classes.toArray(new String[classes.size()]);
}
}

配置文件

custome.importselector.expression= com.helius.service.impl.*

这个自定义选择器的注释已经很丰富 了,这个类的作用就是:

优化建议:

  • 未用@componscan注解指定扫描的包时,默认扫描的是@import注解所在的包。

    可以再次添加一个配置文件,在配置文件指定我们需要扫描的包,在代码中加入逻辑:若@component不存在或未指定,则使用配置文件中指定的路径进行扫描。

@Import导入自定义选择器的更多相关文章

  1. windows 下Python import 导入自定义模块

    周末在家研究这个东西,则找到解决方案. 费话少说,上代码 #定义一个自定义的函数,如下 #函数的名称必须是字母和数字的组合,不能用数字开头 #函数名后用小括号括住入参,可以用逗号分隔多个 #如果有返回 ...

  2. Python使用import导入模块时执行了模块的文件但报ModuleNotFoundError错误的愚蠢问题

    老猿在学习import导入自定义模块时,搜索路径中sys.path中已经添加对应路径,发现会报ModuleNotFoundError,但对应的模块代码被执行了,代码myfib.py如下: def fi ...

  3. 关于CSS各种选择器,还有各种引入样式表的区别,import导入样式表,在介绍一些伪类选择器

    (一)CSS选择器: 1.标签选择器:通过HTML的标签名直接选择该标签 2.类选择器:通过.选择器的名称{} 来对添加了class属性的标签进行选中 3.ID选择器:通过#选择器的名称{} 来对添加 ...

  4. Python导入自定义类时显示错误:attempted relative import beyond top-level package

    显示这个错误可能有两个原因: 1.文件夹中没有包含__init__.py文件,该文件可以为空,但必须存在该文件. 2.把该文件当成主函数入口,该文件所在文件夹不能被解释器视作package,所以可能导 ...

  5. java 导入自定义类

    eclipse导入很容易,昨天上课学了一下用记事本写java,导入自定义类,这就麻烦了. 代码贴一下,方便操作: package tom.jiafei; public class SquareEqua ...

  6. Python3导入自定义模块的3种方式

    前话 最近跟着廖雪峰的教程学到 模块 这一节.关于如何自定义一个模块,如果大家不懂的话还请先看下面这篇博文 ↓ http://www.liaoxuefeng.com/wiki/001431608955 ...

  7. 模块(modue)和包(package)的概念-import导入模块

    模块 在计算机程序的开发过程中,随着程序代码越写越多,在一个文件里代码就会越来越长,越来越不容易维护. 为了编写可维护的代码,我们把很多函数分组,分别放到不同的文件里,这样,每个文件包含的代码就相对较 ...

  8. python笔记-1(import导入、time/datetime/random/os/sys模块)

    python笔记-6(import导入.time/datetime/random/os/sys模块)   一.了解模块导入的基本知识 此部分此处不展开细说import导入,仅写几个点目前的认知即可.其 ...

  9. python笔记-6(import导入、time/datetime/random/os/sys模块)

    一.了解模块导入的基本知识 此部分此处不展开细说import导入,仅写几个点目前的认知即可.其它内容待日后有深入理解了再来细说 1.import可以导入的两种不同的内容 1.1 *.py文件结尾的文件 ...

随机推荐

  1. tempermonkey文档及为google翻译添加清除输入框脚本

    想通过tempermonkey为google增加一个清除输入框的快捷键,这本来是很好做的事情,后来也证明确实是那么简单,不过中间遇到了几个奇怪的问题,有必要记录一下 tempermonkey 文档:h ...

  2. from import语句

    *)假如导入出现了问题,那么一定是导入的文件里的语法问题或者其他问题 参考链接:http://www.cnblogs.com/hwf-73/p/5493328.html 1)导入时重命名 as fro ...

  3. python 排序 堆排序

    算法思想 : 堆排序利用堆数据结构设计的一种排序算法,堆是一种近似完全二叉树的结构,同时满足堆积的性质,即对于任意的i均有ki>=k(2i+1),ki>=k(2i+2) 步骤: 将数组转化 ...

  4. mysql锁机制总结,以及优化建议

    一.锁概述和分类 二.表锁 偏向MyISAM存储引擎,开销小,加锁快:无死锁:锁定粒度大,发生锁冲突的概率最高,并发度最低. [手动增加表锁] lock table 表名字1 read(write), ...

  5. python每日经典算法题5(基础题)+1(较难题)

    一:基础算法题5道 1.阿姆斯特朗数 如果一个n位正整数等于其各位数字的n次方之和,则称该数为阿姆斯特朗数.判断用户输入的数字是否为阿姆斯特朗数. (1)题目分析:这里要先得到该数是多少位的,然后再把 ...

  6. English--元音

    English|元音 在一开始学习英语的时候,最需要掌握的就是音标.所以需要从音标的元音开始,并且不局限于掌握音标的元音与辅音,大家可以参考下英文版发音课,并不知道只学习元音与辅音,还有各种弱读连读等 ...

  7. Kubernetes CNI网络插件

    CNI 容器网络接口,就是在网络解决方案由网络插件提供,这些插件配置容器网络则通过CNI定义的接口来完成,也就是CNI定义的是容器运行环境与网络插件之间的接口规范.这个接口只关心容器的网络连接,在创建 ...

  8. druid + mysql + mybatis 批量更新报错

    首先 批量更新报错 sql injection violation, multi-statement not allow 然后看了博客:https://blog.csdn.net/qq_3634595 ...

  9. rsync免密码远程复制文件

    目标: 从云服务器(112.77.69.212)把mongodb中的文件同步到本地. 步骤一:在云服务器上创建用户 $ adduser monbak $ passwd monbak 步骤二:设置免密登 ...

  10. helm搭建本地chart仓库及基本操作

    这个步骤,是配合公司的竞赛. 因为公司这次的环境,我们只有namespace权限,而没有整个集群的管理, 而且,公司没有提供统一的helm chart repo, 所以只能自建. 参考URL: htt ...