Spring源码探究1.0

简单看了看写了些,Spring最简单的一个实现,实现了什么具体如下

一、 初始化阶段

步骤序号 初始化阶段 核心方法 主要作用 关键数据结构变化
1 加载配置文件 doLoadConfig() 读取 contextConfigLocation 指定的配置文件(如 application.properties contextConfig 中加载 scanPackage
2 包扫描 doScanner() 根据 scanPackage 扫描所有 .class 文件 classNames 保存所有全限定类名
3 IoC 实例化 doInstance() @GPController@GPService 标注的类进行实例化 ioc 中放入 Bean 实例
4 依赖注入(DI) doAutowired() @GPAutowired 字段注入依赖 ioc 内对象完成属性赋值
5 初始化映射关系 doInitHandlerMapping() 建立 URL → Method 的映射关系 handlerMapping 填充
6 初始化完成 init() 结束 框架启动完成,可接收请求 MVC 框架可工作

doLoadConfig

扫描相关类

IoC 实例化

String className : classNames

来我自己聊聊

注解扫描

GPController

clazz 反射实例化,然后添加进容器,name 和calss

GPService

@GPService 获取value

如果有,优选name

2.正常注入

3.接口获取

2️⃣ 为什么要把接口也放进 IOC?

这一步的目的只有一个:@GPAutowired

private UserService userService;

key = "com.xxx.UserService"

value = UserServiceImpl 的实例

复制代码
private void doInstance() {
        if(classNames.isEmpty()){return;}
        try {
            for (String className : classNames) {
                Class<?> clazz = Class.forName(className);
                if(clazz.isAnnotationPresent(GPController.class)) {
                    //key提取出来了,把value也搞出来
                    String beanName = toLowerFirstCase(clazz.getSimpleName());
                    Object instance = clazz.newInstance();
                    ioc.put(beanName, instance);
                }else if(clazz.isAnnotationPresent(GPService.class)){
                    //1、在多个包下出现相同的类名,只能寄几(自己)起一个全局唯一的名字
                    //自定义命名
                    String beanName = clazz.getAnnotation(GPService.class).value();
                    if("".equals(beanName.trim())){
                        beanName = toLowerFirstCase(clazz.getSimpleName());
                    }

                    //2、默认的类名首字母小写
                    Object instance = clazz.newInstance();
                    ioc.put(beanName, instance);

                    //3、如果是接口
                    //判断有多少个实现类,如果只有一个,默认就选择这个实现类
                    //如果有多个,只能抛异常
                    for (Class<?> i : clazz.getInterfaces()) {
                        if(ioc.containsKey(i.getName())){
                            throw new Exception("The " + i.getName() + " is exists!!");
                        }
                        ioc.put(i.getName(),instance);
                    }

                }else{
                    continue;
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }

    }

依赖注入

思路

扫描bean下的,方法,是否有对应注解,如果有,那么根据ioc容器的类型名字拿取bean

然后反射bean下的变量进行set

初始化HandlerMapping

映射,拿取conroller的注解,拿取method上的注解,拿出url 。然后映射,url对应method。

public class GPDispatchServlet extends HttpServlet

HttpServlet 是 Java EE(Jakarta EE)中提供的HTTP 协议专用 Servlet 基类,它封装了对 HTTP 请求的处理逻辑。GPDispatchServlet 继承 HttpServlet 的核心作用是复用 HttpServlet 提供的成熟 Web 请求处理骨架,无需从零实现 Servlet 的底层规范,直接获得处理 HTTP GET/POST 等请求的能力。

在这份手写简易 Spring MVC 框架的代码中,GPDispatchServlet 并非一个普通的 Servlet,而是整个 MVC

框架的核心前端控制器(Front Controller),这是一种经典的设计模式应用。 它的核心职责是统一接收所有客户端的 HTTP

请求,作为请求入口的 "总闸门",再将请求分发给对应的业务处理组件(如 DemoAction 中的具体方法),而非为每个业务功能创建单独的

Servlet。

委派

思路,继承servlet

获取前端控制器,写doget 和post 写调用器

作用

拿取request的url,跟urlmap进行对应。如果对应上。那么进入执行

1.参数处理

2.根据method拿去calss的名字,然后进行反射invoke

url对应

http://localhost:8080/gupaoedu_vip_spring_war/demo/query?name=Jerry

params = {ParameterMap@3166} size = 1

"name" -> {String[1]@3173} ["Jerry"]

很有意思的参数处理

GPRequestParam

运行

控制器

相关推荐
曹牧2 小时前
BeanUtils.copyProperties‌
java
changhong19862 小时前
如何在 Spring Boot 中配置数据库?
数据库·spring boot·后端
QWQ___qwq2 小时前
Java线程安全深度总结:基本类型与引用类型的本质区别
java·安全·面试
识君啊3 小时前
Java异常处理:中小厂面试通关指南
java·开发语言·面试·异常处理·exception·中小厂
月月玩代码4 小时前
Actuator,Spring Boot应用监控与管理端点!
java·spring boot·后端
XPoet5 小时前
AI 编程工程化:Skill——给你的 AI 员工装上技能包
前端·后端·ai编程
阿珍爱上了阿强,在一个有星星的夜晚5 小时前
node后端页面性能监测分析
java·学习方法
Java程序之猿5 小时前
SpringBoot + camel+IBM MQ实现消息队列处理
java·spring boot·mybatis
码事漫谈6 小时前
从“功能实现”到“深度优化”:金仓数据库连接条件下推技术的演进之路
后端