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 小时前
Golang原理剖析(程序初始化、数据结构string)
开发语言·数据结构·经验分享·后端·golang·string·init
韩立学长2 小时前
【开题答辩实录分享】以《以体验为中心的小学古诗互动学习App的设计及实现》为例进行选题答辩实录分享
java·spring·安卓
萤丰信息2 小时前
科技赋能智慧园区:解码绿色转型的“数字密码”
java·大数据·人工智能·科技·安全·智慧城市·智慧园区
小鸡脚来咯2 小时前
RESTful API 面试详解
后端·面试·restful
吴巴格2 小时前
springboot引用其他中间件,如何确定版本
spring boot·后端·中间件
码农阿豪2 小时前
远程调试不再难!Remote JVM Debug+cpolar 让内网 Java 程序调试变简单
java·开发语言·jvm
stillaliveQEJ2 小时前
【JavaEE】Spring AOP(二)
java·spring·java-ee
IT_陈寒2 小时前
Vue3性能优化实战:5个被低估的API让我减少了40%的代码量
前端·人工智能·后端
岁岁种桃花儿2 小时前
Spring Boot项目核心配置:parent父项目详解(附实操指南)
java·spring boot·spring