首页 > 其他分享 >获取指定路径,扫描路径下指定类(仿Spring)

获取指定路径,扫描路径下指定类(仿Spring)

时间:2023-01-19 11:05:08浏览次数:35  
标签:String Spring 路径 指定 public 注解 class


本文目标:传入指定路径,扫描对应路径下符合要求的类,并添加到指定的集合中。


其原型是Spring中初始化容器类的一部分。当然本例仅仅完成基本功能,没有考虑过多功能——即Spring中配置对应的CompontScan路径,并在类上添加@Component注解,即可完成将一个类添加到Spring容器。

文章目录

  • ​​1、文件整体目录结构​​
  • ​​2、自定义注解​​
  • ​​3、编写被测试对象类​​
  • ​​4、编写一个配置类​​
  • ​​5、编写BeanDefinition类​​
  • ​​6、编写容器类(重点)​​
  • ​​7、测试类​​



自定义两个注解(2个):类比理解Spring中@Component、@ComponentScan注解

自定义MobianContext容器类(1个):类比理解Spring中AnnotationConfigApplicationContext

自定义MobianBeanDefinition类(1个):类比理解Spring中的BeanDefinition

自定义MobianConfig配置类(1个):类比理解Spring中的我们自己自定义的配置类


1、文件整体目录结构

获取指定路径,扫描路径下指定类(仿Spring)_容器类


2、自定义注解

这两个注解仅有最基础的功能,且必须配置对应的value值

MobianScan的value用于配置扫描路径

MobianComponent的value用来配置类的别名

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MobianScan {
String value();
}
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MobianComponent {
String value();
}


3、编写被测试对象类

随便写的几个类,部门类添加指定的注解,并且配置别名信息

@MobianComponent("teacher")
public class TeacherService {
}
public class StudentService {
}
public interface SchoolService {
void show();
}
@MobianComponent("schoolService")
public class SchoolServiceImpl implements SchoolService {

@Override
public void show() {
}
}


4、编写一个配置类

初始化context容器时使用

其创建是为了模仿spring的配置类,本例中仅需要使用配置的路径

@MobianScan("pers.imitationspring.service")
public class MobianConfig {
}


5、编写BeanDefinition类

这里的作用和Spring中对应的类作用相同,用来存放所有Bean的初始化信息,只是本例中比较简单

public class MobianBeanDefinition {
private Class clazz;

public Class getClazz() {return clazz;}
public void setClazz(Class clazz) {this.clazz = clazz;}
}


6、编写容器类(重点)

具体细节以在代码中给出注释,主要步骤分为以下几步:

  1. 解析传入配置类上@MobianComponentScan注解配置的包路径
  2. 将包路径转化为url路径
  3. 根据url路径定位到具体的文件位置,完成文件夹下文件的遍历
  4. 将具体文件的文件位置,转化为类加载能够识别的包路径
  5. 使用类加载器加载具体的,此时可以完成类的加载
  6. 解析类上的@MobianComponent配置的类的别名信息
  7. 将类的别名信息以及类信息存储到beanDefinitionMap中
public class MobianContext {

// 存放所有扫描出来的Bean,等价于Spring中的beanDefinitionMap集合
ConcurrentHashMap<String, MobianBeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>();

public MobianContext(Class config) throws ClassNotFoundException {

if (config.isAnnotationPresent(MobianScan.class)) {
MobianScan scanAnno = (MobianScan) config.getAnnotation(MobianScan.class);
// 获取注解中配置的路径
String scanPath = scanAnno.value();

// 将对应的路径转化为路径格式
String scanUrl = scanPath.replace(".", "/");

// 通过类加载器,传入相对于当前项目的路径(target/classes目录下),查找指定的资源
// scanUrl:pers/imitationspring/service
ClassLoader loader = MobianContext.class.getClassLoader();
URL resource = loader.getResource(scanUrl);

// resource : file:/E:/Softwareworkspace/ideaworkspace/writespring/target/classes/pers/imitationspring/service
if (resource != null) {
// 获取对应路径资源下的所有文件
File files = new File(resource.getFile());

// 遍历对应的文件
for (File file : files.listFiles()) {

// 获取当前文件的绝对路径
String path = file.getAbsolutePath();
// 切割路径字符串,拿到相对路径
String classPath = path.substring(path.indexOf("pers"), path.indexOf(".class"));
// 将相对路径转换为包结构
classPath = classPath.replace("\\", ".");

// 根据类的路径去创建一个对象,此时已经能获取到对应的类信息
Class<?> aClass = loader.loadClass(classPath);
System.out.println(aClass);
// 获取类上对应的注解
MobianComponent componentAnno = aClass.getAnnotation(MobianComponent.class);
if (componentAnno != null) {
// 在Component注解不为空的情况下,获取注解内的信息(即类注册的别名)
String beanName = componentAnno.value();
MobianBeanDefinition beanDefinition = new MobianBeanDefinition();
beanDefinition.setClazz(aClass);
// 将类别名和类信息存储到beanDefinitionMap中
beanDefinitionMap.put(beanName, beanDefinition);
}
}
}
}
}


// 获取beanDefinitionMap集合中存储的所用信息
public void printBeanDefinitionMap() {
for (Map.Entry<String, MobianBeanDefinition> bd : beanDefinitionMap.entrySet()) {
System.out.println(bd.getKey() + " : " + bd.getValue().getClazz());
}
}
}


7、测试类

初始化Context容器类,打印beanDefinitionMap集合内容(所有满足要求的类)

public class Test {
public static void main(String[] args) throws ClassNotFoundException {

MobianContext context = new MobianContext(MobianConfig.class);
System.out.println("====");
context.printBeanDefinitionMap();
}
}

测试结果:

获取指定路径,扫描路径下指定类(仿Spring)_spring_02


即我们配置的扫描路径下面包含3个类1个接口,但是符合要求的(@MobianComponent)类只有2个,满足要求的类的别名分别时teacher和是schoolService。


标签:String,Spring,路径,指定,public,注解,class
From: https://blog.51cto.com/u_15942107/6019937

相关文章

  • 浅谈Spring中Bean的生命周期
    文章目录​​1、基本概念​​​​2、生命周期流程图​​​​3、源码与功能分析​​​​3.1、实例化前​​​​3.2、实例化​​​​3.3、实例化后​​​​3.4、初始化前前​......
  • SpringCloud(二)
    文章目录​​6、Ribbon​​​​6.1、Ribbon是什么​​​​6.2、Ribbon能干什么​​​​6.3、Ribbon实现负载均衡环境搭建​​​​6.4、Ribbon实现负载均衡​​​​6.5、自定......
  • Spring
    全文大纲​​1、Spring​​​​1.1、简介​​​​1.2、优点​​​​1.3、组成(七大模块)​​​​1.4、拓展​​​​2、IOC理论推导​​​​2.1、最初的开发​​​​2.2、改进......
  • 学习笔记——Spring声明式事务管理属性(隔离级别、事务超时、事务只读、事务回滚);Spring
    2023-01-19Spring声明式事务管理属性一、隔离级别1、概念:一个事务与其他事务之间的隔离等级(1,2,4,8)。2、隔离级别:(1)读未提交(1):READUNCOMMTTED存在问题:脏读(读取到了未......
  • ElasticSearch全文搜索引擎 -Spring Boot操作ES(SpringData概述、Spring Data Elastics
    文章目录​​1.SpringData概述​​​​2.SpringDataElasticsearch​​​​3.实现基本操作​​​​4.ElasticSearch操作文档​​​​5.ElasticSearch原生API操作工具......
  • Spring Batch多步骤任务、并行执行、任务决策器、任务嵌套
    道虽迩(ěr),不行不至,事虽小,不为不成......
  • Spring-webflux 响应式编程
    热爱可抵漫长岁月文章目录​​1.前言​​​​2.Spring-webflux简介​​​​3.什么是“响应式”​​​​4.Spring-webflux的响应式API​​​​5.SpringMVC还是WebFlu......
  • Spring自定义启动图标(个性化启动图标)
     今天比昨天好,这就是希望。☀️☀️☀️ 文章目录​​个性化输出​​​​图片转换输出​​​​生成banner的网站​​Spring默认启动输出.________......
  • SpringCloud Tencent Polaris
    北极星是腾讯开源的服务发现和治理中心,致力于解决分布式或者微服务架构中的服务可见、故障容错、流量控制和安全问题。虽然,业界已经有些组件可以解决其中一部分问题,但是缺少......
  • SpringBoot+MyBatils-puls+db2
    记录自己搭建db2数据库,链接数据库遇到的问题。 搭建db2我是在阿里云使用docker搭建的db2数据库,搭建数据库参考下面这个链接https://www.cnblogs.com/Yongzhouunknown/p......