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" -> {String1@3173} "Jerry"

很有意思的参数处理

GPRequestParam

运行

控制器

相关推荐
Mark_ZP24 分钟前
【锁1】Synchronized vs ReentrantLock区别
java
立心者01 小时前
SpringBoot中使用TOTP实现MFA(多因素认证)
java·spring boot·后端
枕星而眠1 小时前
C++ STL Map容器完全指南:从有序红黑树到无序哈希表
java·开发语言
AskHarries2 小时前
SEO 页面怎么生成
后端
爱吃牛肉的大老虎2 小时前
Rust对象之结构体,枚举,特性
开发语言·后端·rust
石榴2 小时前
NestJS 的请求到底经过了什么:装饰器、守卫、拦截器、管道与中间件如何配合
后端
bbq粉刷匠2 小时前
HashMap 底层原理深度拆解(二):putVal 完整链路解析(懒加载 · 链表遍历 · 尾插法)
java·开发语言·哈希算法
Gopher_HBo2 小时前
moby-client客户端
后端
Sam_Deep_Thinking2 小时前
一个靠谱的C端网关服务应该包含什么内容
java·程序员·系统架构
杨运交3 小时前
[055][调度模块]Spring动态任务调度框架的设计与实现
java·后端·spring