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

运行

控制器

相关推荐
颜酱8 小时前
图结构完全解析:从基础概念到遍历实现
javascript·后端·算法
Coder_Boy_8 小时前
技术让开发更轻松的底层矛盾
java·大数据·数据库·人工智能·深度学习
invicinble9 小时前
对tomcat的提供的功能与底层拓扑结构与实现机制的理解
java·tomcat
较真的菜鸟9 小时前
使用ASM和agent监控属性变化
java
黎雁·泠崖9 小时前
【魔法森林冒险】5/14 Allen类(三):任务进度与状态管理
java·开发语言
qq_124987075310 小时前
基于SSM的动物保护系统的设计与实现(源码+论文+部署+安装)
java·数据库·spring boot·毕业设计·ssm·计算机毕业设计
Coder_Boy_10 小时前
基于SpringAI的在线考试系统-考试系统开发流程案例
java·数据库·人工智能·spring boot·后端
Mr_sun.10 小时前
Day06——权限认证-项目集成
java
瑶山11 小时前
Spring Cloud微服务搭建四、集成RocketMQ消息队列
java·spring cloud·微服务·rocketmq·dashboard
abluckyboy11 小时前
Java 实现求 n 的 n^n 次方的最后一位数字
java·python·算法