手写模拟spring扫描底层实现

  • 前言
    • 1、ApplicationContext和AppConfig
    • 2、@Component和@ComponentScan注解
    • 3、UserService和Test

前言

最近也是开始学习了Spring的一些底层,学习的最好方法就是自己实现,所以也是跟着视频自己手写一个模拟spring,其中对一些知识也是会总结和讲解自己的理解。

1、ApplicationContext和AppConfig

我们首先需要模拟的是spring的自动扫描机制,我们来想一下,当spring容器启动,自动扫描的时候,首先是肯定不能缺少启动类的,也就是我们的ApplicationContext,所以我们先创建一个ApplicationContext。

回想一下,我们之前手动去配置spring.xml的时候,是要通过启动配置ApplicationContext将配置文件进行读取,所以我们先要写一个spring的配置类 AppConfig,当然,我们这里并不进行一些复杂的配置。

/*** @author zal* @date 2022年08月30日 16:23* @Description Spring容器配置类*/
@ComponentScan("com.zal.service")
public class AppConfig {}

然后将这个AppConfig注入到我们的启动类ZalApplicationContext中,实现基本的配置读取。

/*** @author zal* @date 2022年08月30日 16:21* @Description 模拟Spring容器启动类*/
public class ZalApplicationContext {private Class configClass;/*** 创建一个Spring容器** @param configClass*/public ZalApplicationContext(Class configClass) {this.configClass = configClass;}
}

2、@Component和@ComponentScan注解

我们知道,Spring的扫描是通过类上是否加上了注解@Component来进行判断的,而@ComponentScan 注解则是配置扫描包的路径的,所以我们要实现一下这两个注解。

/*** @author zal* @date 2022年08月30日 16:20* @Description 模仿spring的bean注入的注解* @Target(ElementType.TYPE)  表示只能作用在类的上面* @Retention(RetentionPolicy.RUNTIME) 表示作用在运行时*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Component {String value() default "";
}
/*** @author zal* @date 2022年08月30日 16:20* @Description 模仿spring路径扫描的注解* @Target(ElementType.TYPE)  表示只能作用在类的上面* @Retention(RetentionPolicy.RUNTIME) 表示作用在运行时*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ComponentScan {String value() default "";
}

3、UserService和Test

拥有了Spring启动类以及相关扫描的注解之后,我们需要一个被扫描的服务以及对应的测试方法,所以我们这里自定义一个UserService,给这个类加上相应的注解后进行扫描逻逻辑的编写。

@Component("userService")
public class UserService {// 代码
}
public class Test {public static void main(String[] args) {ZalApplicationContext applicationContext = new ZalApplicationContext(AppConfig.class);// 我们拿到spring容器后,肯定是要进行获取bean的操作的// 获取bean的操作我们放在下篇文章讲解applicationContext.getBean("userService");}
}

最后是ZalApplicationContext进行扫描的逻辑实现,如下代码

public class ZalApplicationContext {private Class configClass;/*** 创建一个Spring容器** @param configClass*/public ZalApplicationContext(Class configClass) {this.configClass = configClass;// 扫描// 判断传入的配置类上是否添加了ComponentScan注解if (configClass.isAnnotationPresent(ComponentScan.class)) {// 获取注解的信息ComponentScan componentScanAnnotation = (ComponentScan) configClass.getAnnotation(ComponentScan.class);// 获取扫描路径(就是注解上添加的包路径),如com.zal.serviceString path = componentScanAnnotation.value();// 处理路径字符串,将.替换为/,如com/zal/servicepath = path.replace(".", "/");//获取容器的类加载器,获取class文件的绝对路径 如F:/web/zal-spring/out/production/zal-spring/com/zal/serviceClassLoader classLoader = ZalApplicationContext.class.getClassLoader();URL resource = classLoader.getResource(path);// 将class文件封装为一个文件或者是文件夹File file = new File(resource.getFile());if (file.isDirectory()) {// 拿到当前文件夹中的所有文件File[] files = file.listFiles();for (File f : files) {// 拿到文件的绝对路径String fileName = f.getAbsolutePath();// 判断文件是否以class结尾if (fileName.endsWith(".class")) {// 获取class文件的全限定类名,如com.zal.service.UserServiceString className = fileName.substring(fileName.indexOf("com"), fileName.indexOf(".class")).replace("\\", ".");try {// 如何获取class对象呢? 这就涉及到类的加载Class<?> clazz = classLoader.loadClass(className);// 判断这个类是否是一个bean,条件是类上是否有@Component注解if (clazz.isAnnotationPresent(Component.class)) {//bean的创建操作}} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {e.printStackTrace();}}}}}}
}

以上实现只是一个简单的模拟spring底层扫描的逻辑代码,表示spring扫描的一个简单的逻辑,并不是真正的spring底层扫描实现,只是为了更好的让我们去了解底层实现的一个思想。

手写模拟spring扫描底层实现相关推荐

  1. 【Spring系列】- 手写模拟Spring框架

    简单模拟Spring

  2. c++socket多个客户端通过不同端口与一个服务端通信_手写RPC,深入底层理解整个RPC通信...

    一.前言 RPC,远程过程调用,调用远程方法像调用本地方法一样.RPC交互分为客户端和服务端,客户端调用服务端方法,服务端接收数据并打印到控制台,并response响应给客户端. RPC和HTTP的联 ...

  3. spring源码分析01-(前期准备)spring核心原理解析和手写简易spring

    1.本文主要介绍内容 本文会把Spring中核心知识点大概解释下.可以对Spring的底层有一个整体的大致了解.主要内容包括: 手写简易spring框架,帮助更好理解spring. 代码点击链接自取 ...

  4. 手写实现Spring(IOC、DI),SpringMVC基础功能

    手写实现Spring(IOC.DI),SpringMVC功能 spring和springMVC的用法相信大家都不陌生,我简单讲下我实现的思路 spring阶段 事项 配置 配置web.xml: ini ...

  5. 从 0 开始手写一个 Spring MVC 框架,向高手进阶

    转载自   从 0 开始手写一个 Spring MVC 框架,向高手进阶 Spring框架对于Java后端程序员来说再熟悉不过了,以前只知道它用的反射实现的,但了解之后才知道有很多巧妙的设计在里面.如 ...

  6. 自己手写一个Spring MVC框架

    想要了解Spring MVC框架的原理,探究框架是如何设计的,不错的学习方式是阅读源码,然后自己手写一个框架.本文带领大家简化的手写一个Spring MVC框架. Spring框架对于Java后端程序 ...

  7. 【重难点】【JUC 03】怎么实现一个线程安全的队列、手写模拟实现一个阻塞队列

    [重难点][JUC 03]怎么实现一个线程安全的队列.手写模拟实现一个阻塞队列 文章目录 [重难点][JUC 03]怎么实现一个线程安全的队列.手写模拟实现一个阻塞队列 一.怎么实现一个线程安全的队列 ...

  8. 手写简易Spring

    项目描述 项目描述: 手写Spring启动以及扫描流程 手下getBean()流程 手写Bean生命周期流程 手写依赖注入流程 手写BeanPOSTProcessor机制 手写AOP机制 0. Spr ...

  9. 我居然手写了Spring框架

    手写完了 刚参加工作那会接触java还是用的struct的时代,后面在SSH火爆时代的时候我转战.net,多年之后公司转java技术栈已经是Spring的天下,源码嚼了很多遍于是很想尝试把这套东西用在 ...

最新文章

  1. php图片特效,php_imagick实现图片剪切、旋转、锐化、减色或增加特效的方法
  2. C语言之typedef详解
  3. HDU - 4388 Stone Game II(博弈+思维)
  4. 学习笔记(51):Python实战编程-ListBox
  5. node中的Stream-Readable和Writeable解读
  6. Win11系统如何设置黑暗模式
  7. 作为现代计算机理论的基础的,作为现代计算机理论基础的冯·诺依曼原理和思想是()。...
  8. Leetcode每日一题:54.spiral-matrix(螺旋矩阵)
  9. AD的命名规则 AD常用产品型号命名规则
  10. 通过批处理来运行python程序
  11. Flutter进阶第7篇: 调用原生硬件Api实现照相机拍照和相册选择 以及拍照上传到服务器
  12. 笔记本新机全新安装XP时遇到问题的解决方案(针对新的Vista机型装xp的解决方案)...
  13. 读书笔记:《牛奶可乐经济学》
  14. Python实现网页自动截图
  15. 数论--P8845 [传智杯 #4 初赛] 小卡和质数
  16. 游戏开发九宫格战斗架构解析具体解释
  17. 做一个女孩喜欢的绅士男人
  18. 媳妇儿喜欢玩某音中的动漫特效,那我就用python做一个图片转化软件。
  19. 规则引擎drools系列(一)
  20. 时序建模:时间戳与时序特征衍生思路汇总

热门文章

  1. 读书笔记1 PPT设计之道
  2. 日志审计(启明设备)
  3. ORACLE各种对象、概念及关系整理(一文读懂)
  4. pycharm连接mysql5.7
  5. LED驱动程序第一课
  6. VB源码之友终于开发完毕了
  7. CVPR 2021放榜,腾讯优图20篇论文都在这里了!
  8. 从GCT的成绩看问题
  9. 成立一家投资管理有限公司的资本是多少?
  10. 计算机如何访问苹果6s的相册,如何在电脑中打开苹果手机中的HEIC格式的照片?...