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

运行

控制器

相关推荐
tb_first1 分钟前
SSM速通3
java·jvm·spring boot·mybatis
独自破碎E7 分钟前
总持续时间可被 60 整除的歌曲
java·开发语言
Python+JAVA+大数据11 分钟前
TCP_IP协议栈深度解析
java·网络·python·网络协议·tcp/ip·计算机网络·三次握手
丶小鱼丶11 分钟前
Java基础之【多线程】
java
东东51642 分钟前
基于vue的电商购物网站vue +ssm
java·前端·javascript·vue.js·毕业设计·毕设
她说..1 小时前
策略模式+工厂模式实现审批流(面试问答版)
java·后端·spring·面试·springboot·策略模式·javaee
鹿角片ljp1 小时前
力扣9.回文数-转字符双指针和反转数字
java·数据结构·算法
skywalker_111 小时前
网络编程篇
java·网络协议·网络编程
毕设源码-朱学姐1 小时前
【开题答辩全过程】以 基于Java的九价疫苗预约系统为例,包含答辩的问题和答案
java·开发语言
tb_first1 小时前
SSM速通4
java·jvm·spring·tomcat·maven·mybatis