实现SpringMVC底层机制(二)

文章目录

    • 1. 动态获取spring配置文件
        • 1.修改SunWebApplicationContext.java
        • 2.修改SunDispatcherServlet.java
    • 2.自定义Service注解
        • 1.需求分析
        • 2.编写Monster.java
        • 3.自定义Service注解
        • 4.编写Service接口MonsterService.java
        • 5.编写Service实现类MonsterServiceImpl.java
        • 6.修改SunWebApplicationContext.java的executeInstance方法,增加对Service注解的扫描
        • 7.debug测试
    • 3.完成自定义Autowired注解
        • 1.自定义Autowired注解
        • 2.在SunWebApplicationContext.java中添加方法executeAutoWired完成属性的自动装配
        • 3.修改MonsterController.java来使用Autowired注解
        • 4.单元测试
    • 4.当前阶段完成的任务
        • 自定义两个注解
        • 目前对SpringMVC容器的简单理解

1. 动态获取spring配置文件

1.修改SunWebApplicationContext.java

image-20240227174308452

2.修改SunDispatcherServlet.java

image-20240227174349197

2.自定义Service注解

1.需求分析

image-20240227174740181

2.编写Monster.java
package com.Sun.entity;

/**
 * @author 孙显圣
 * @version 1.0
 */
public class Monster {
    private Integer id;
    private String name;
    private String skill;
    private Integer age;

    public Monster(Integer id, String name, String skill, Integer age) {
        this.id = id;
        this.name = name;
        this.skill = skill;
        this.age = age;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSkill() {
        return skill;
    }

    public void setSkill(String skill) {
        this.skill = skill;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Monster{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", skill='" + skill + '\'' +
                ", age=" + age +
                '}';
    }
}

3.自定义Service注解
package com.Sun.sunspringmvc.annotation;

import java.lang.annotation.*;

/**
 * 自定义注解,用于标识一个service
 *
 * @author 孙显圣
 * @version 1.0
 */
@Target(ElementType.TYPE) //作用于目标是类
@Retention(RetentionPolicy.RUNTIME) //作用范围
@Documented
public @interface Service {
    String value() default "";
}

4.编写Service接口MonsterService.java
package com.Sun.sunspringmvc.annotation;

import java.lang.annotation.*;

/**
 * 自定义注解,用于标识一个service
 *
 * @author 孙显圣
 * @version 1.0
 */
@Target(ElementType.TYPE) //作用于目标是类
@Retention(RetentionPolicy.RUNTIME) //作用范围
@Documented
public @interface Service {
}

5.编写Service实现类MonsterServiceImpl.java
package com.Sun.service.Impl;

import com.Sun.entity.Monster;
import com.Sun.service.MonsterService;
import com.Sun.sunspringmvc.annotation.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * @author 孙显圣
 * @version 1.0
 */
@Service
public class MonsterServiceImpl implements MonsterService {
    public List<Monster> listMonsters() {
        ArrayList<Monster> monsters = new ArrayList<Monster>();
        monsters.add(new Monster(1, "牛魔王", "芭蕉扇", 500));
        monsters.add(new Monster(2, "蜘蛛精", "吐口水", 200));
        return monsters;
    }
}

6.修改SunWebApplicationContext.java的executeInstance方法,增加对Service注解的扫描
    //编写方法,将符合要求的类反射创建对象,并封装到单例池中
    public void executeInstance() {
        //遍历所有全类名
        for (String classPath : classFullPathList) {
            try {
                //反射
                Class<?> aClass = Class.forName(classPath);
                //判断是否有Controller注解
                if (aClass.isAnnotationPresent(Controller.class)) {
                    //有注解,当他是单例的,反射创建bean对象,放到单例池中,默认首字母小写
                    //获取类名首字母小写
                    String name = aClass.getSimpleName().substring(0, 1).toLowerCase() + aClass.getSimpleName().substring(1);
                    //放到单例池中
                    singleObjects.put(name, aClass.newInstance());
                } else if (aClass.isAnnotationPresent(Service.class)) {
                    //获取注解对象
                    Service annotation = aClass.getAnnotation(Service.class);
                    //获取注解的value
                    String value = annotation.value();
                    //为了使注入的都是同一个对象,所以在这里使用反射创建实例
                    Object bean = aClass.newInstance();
                    //如果注解的value是空的,则使用默认机制注入到单例池中
                    if ("".equals(value)) {
                        //1.使用类名首字母小写来注入
                        String simpleName = aClass.getSimpleName();
                        String beanName = simpleName.substring(0,1).toLowerCase() + simpleName.substring(1);
                        singleObjects.put(beanName, bean);
                        //2.使用接口名首字母小写来注入
                        Class<?>[] interfaces = aClass.getInterfaces();
                        //遍历所有接口类型,进行注入
                        for (Class<?> anInterface : interfaces) {
                            //获取接口的名称
                            String interfaceSimpleName = anInterface.getSimpleName();
                            //获取首字母小写
                            String beanName2 = interfaceSimpleName.substring(0,1).toLowerCase() + interfaceSimpleName.substring(1);
                            //进行注入
                            singleObjects.put(beanName2, bean);
                        }
                    } else {
                        //如果value不是空的,则按照value的值进行注入
                        singleObjects.put(value, bean);
                    }
                }
            } catch (ClassNotFoundException e) {
                throw new RuntimeException(e);
            } catch (InstantiationException e) {
                throw new RuntimeException(e);
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            }
        }
    }
7.debug测试

image-20240227192803931

3.完成自定义Autowired注解

1.自定义Autowired注解
package com.Sun.sunspringmvc.annotation;

import java.lang.annotation.*;

/**
 * @author 孙显圣
 * @version 1.0
 */
@Target(ElementType.FIELD) //作用目标是字段
@Retention(RetentionPolicy.RUNTIME) //作用范围
@Documented
public @interface AutoWired {
    String value() default "";
}

2.在SunWebApplicationContext.java中添加方法executeAutoWired完成属性的自动装配

image-20240227205656667

    //编写方法,完成属性的自动装配
    public void executeAutoWired() throws IllegalAccessException {
        //首先判断容器是否为空
        if (singleObjects.isEmpty()) {
            return;
        }
        //遍历容器中的所有bean对象
        for (Object beanObject : singleObjects.values()) {
            //得到Class对象
            Class<?> aClass = beanObject.getClass();
            //得到所有字段
            Field[] declaredFields = aClass.getDeclaredFields();
            for (Field declaredField : declaredFields) {
                //判断这些字段是否有自动装配的注解
                if (declaredField.isAnnotationPresent(AutoWired.class)) {
                    //得到这个注解的value
                    AutoWired annotation = declaredField.getAnnotation(AutoWired.class);
                    String value = annotation.value();

                    Object findBeanObject = null; //用来存储从容器中查找到的值
                    //先判断这个注解的value有没有值
                    if ("".equals(value)) {
                        //如果注解没有值则按照默认的方式处理,即按照类型的首字母小写来查找
                        String simpleName = declaredField.getType().getSimpleName();
                        String beanName = simpleName.substring(0, 1).toLowerCase() + simpleName.substring(1);
                        //从容器中查找
                        findBeanObject = singleObjects.get(beanName);
                    } else {
                        //这个注解的value不是空的,则按照他的这个value在容器中查找
                        findBeanObject = singleObjects.get(value);
                    }

                    if (findBeanObject == null) {
                        throw new RuntimeException("容器中不存在你要装配的bean");
                    } else {
                        //进行依赖注入,需要指定给哪个对象的字段赋值
                        //反射爆破
                        declaredField.setAccessible(true);
                        declaredField.set(beanObject, findBeanObject);
                    }

                }
            }
        }
    }
3.修改MonsterController.java来使用Autowired注解

image-20240227205820110

4.单元测试

image-20240227205910924

image-20240227205928819

4.当前阶段完成的任务

自定义两个注解
  • 自定义Service注解:在原有的扫描所有文件全类名的基础上增加逻辑,判断是否具有Service注解,并根据value值或者默认方案将其注入到bean中
  • 自定义Autowired注解
    • 遍历所有单例池对象,获取对应的Class对象
    • 获取每个对象的所有字段
    • 对每个字段判断是否有Autowired注解,如果有则按照类型首字母小写或者value值来进行依赖注入
目前对SpringMVC容器的简单理解
  • tomcat启动,加载中央控制器
  • 获取spring配置文件路径,使用这个路径创建一个spring容器
  • 调用spring容器的init方法,初始化spring容器
    • 读取配置文件,得到要扫描的包,从而得到包的工作路径
    • 根据工作路径来得到包内所哟class文件的全路径
    • 遍历所有class文件的全路径,得到Class对象
    • 使用反射扫描指定注解,反射创建bean对象,放到单例池中
    • Autowired依赖注入
      • 扫描单例池,得到所有对象,从而得到Class对象
      • 使用反射得到所有字段信息,判断是否有Autowied注解,如果有则根据一定规则从单例池中查找bean对象进行依赖注入
  • 初始化映射对象列表
    • 扫描单例池,得到Class对象
    • 通过反射判断是否有RequestMapping注解,如果有则使用反射获取url和Method对象,再加上当前的对象,封装到映射对象中
    • 将这个映射对象添加到映射对象列表
  • 请求分发
    • 浏览器向中央控制器发送请求
    • 中央控制器根据请求的uri和映射对象列表的url进行比对
    • 如果匹配则反射调用Controller的方法

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/576603.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

数据结构系列-二叉树之前序遍历

&#x1f308;个人主页&#xff1a;羽晨同学 &#x1f4ab;个人格言:“成为自己未来的主人~” 这篇文章&#xff0c;我们主要的内容是对二叉树当中的前历的算法进行讲解&#xff0c;二叉树中的算法所要求实现的是 从根到左子树再到右子树的遍历顺序&#xff0c;可能这样不太…

C语言--基础面试真题

1、局部变量和静态变量的区别 普通局部变量和静态局部变量区别 存储位置&#xff1a; 普通局部变量存储在栈上 静态局部变量存储在静态存储区 生命周期&#xff1a; 当函数执行完毕时&#xff0c;普通局部变量会被销毁 静态局部变量的生命周期则是整个程序运行期间&#…

程序员学CFA——数量分析方法(四)

数量分析方法&#xff08;四&#xff09; 常见概率分布基本概念离散型随机变量与连续型随机变量离散型随机变量连续型随机变量 分布函数概率密度函数&#xff08;PDF&#xff09;累积分布函数&#xff08;CDF&#xff09; 离散分布离散均匀分布伯努利分布二项分布定义股价二叉树…

Rabbitmq安装延迟插件rabbitmq_delayed_message_exchange失败

Docker里的Rabbitmq容器安装延迟插件rabbitmq_delayed_message_exchange失败 一启动插件Rabbitmq容器直接停止运行了 rabbitmq-plugins enable rabbitmq_delayed_message_exchange排除了版本问题和端口问题等&#xff0c;发现是虚拟机运行内存不够&#xff0c;增加虚拟机运行内…

python基础——正则表达式

&#x1f4dd;前言&#xff1a; 这篇文章主要想讲解一下python中的正则表达式&#xff1a; 1&#xff0c;什么是正则表达式 2&#xff0c;re模块三匹配 3&#xff0c;元字符匹配 4&#xff0c;具体示例 &#x1f3ac;个人简介&#xff1a;努力学习ing &#x1f4cb;个人专栏&am…

Hybrid Homomorphic Encryption:SE + HE

参考文献&#xff1a; [NLV11] Naehrig M, Lauter K, Vaikuntanathan V. Can homomorphic encryption be practical?[C]//Proceedings of the 3rd ACM workshop on Cloud computing security workshop. 2011: 113-124.[MJS16] Maux P, Journault A, Standaert F X, et al. To…

【定制化体验:使用Spring Boot自动配置,打造个性化Starter】

项目结构 Pom <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/POM/4…

yml文件修改工具

导入一个 yml 配置文件 可以根据给定的 name 源文件内容 举例如下 - alterId: 0cipher: autoname: 链接1port: 11004server: dotu-hkv1.03ezhg0qsa.downloadskip-cert-verify: truetls: falsetype: tpyudp: trueuuid: ac1f3b35-1d03-3a85-beab-根据name 可以快速将源内容进行替…

系统启动之后创建的第一个窗口是什么?

com.android.settings TYPE_BASE_APPLICATION 1 &#xff1b; 启动时显示的窗口有&#xff1a; 系统窗口有: TYPE_STATUS_BAR TYPE_SEARCH_BAR TYPE_PHONE TYPE_SYSTEM_ALERT TYPE_KEYGUARD TYPE_TOAST TYPE_SYSTEM_OVERLAY TYPE_PRIORITY_PHONE TYPE_SYSTEM_DIALOG…

Synchronized关键字的深入分析

一、引言 在多线程编程中&#xff0c;正确地管理并发是确保程序正确运行的关键。Java提供了多种同步工具&#xff0c;其中synchronized关键字是最基本且最常用的同步机制之一。本文旨在深入解析synchronized的实现原理&#xff0c;探讨其在不同应用场景中的使用&#xff0c;并…

创新书荐|用《创新者的窘境》指导企业应对AI颠覆技术避免被颠覆

如何利用《创新者的窘境》应对AI的颠覆性技术时&#xff0c;了解并实施正确的战略对于确保企业在动荡的市场环境中保持增长和竞争力至关重要。我们分析了市场领导者和初创公司如何利用AI开辟新的增长路径&#xff0c;以及企业如何在技术革命中维持竞争优势。想要深入了解并实践…

CogVLM CogAgent模型部署

CogVLM & CogAgent 下载地址 CogVLM & CogAgent 的 Github 官方仓库&#xff1a;https://github.com/THUDM/CogVLM CogVLM & CogAge…

了解ASK模块STX883Pro和超外接收模块SRX883Pro的独特之处 STX883Pro模块具有以下特点:

高发射功率&#xff1a;STX883Pro具有较高的发射功率&#xff0c;可实现长距离的信号传输&#xff0c;适用于需要覆盖广泛区域的应用场景。 高频率稳定性&#xff1a;具备稳定的频率输出&#xff0c;确保信号传输的可靠性和一致性&#xff0c;避免频率漂移导致的通信故障。 大…

异常检测 | SVDD支持向量数据描述异常数据检测(Matlab)

异常检测 | SVDD支持向量数据描述异常数据检测&#xff08;Matlab&#xff09; 目录 异常检测 | SVDD支持向量数据描述异常数据检测&#xff08;Matlab&#xff09;效果一览基本介绍程序设计参考资料 效果一览 基本介绍 用于一类或二元分类的 SVDD 模型 多种核函数&#xff08;…

基于模糊控制的电动汽车锂电池SOC主动均衡电路MATLAB仿真模型

微❤关注“电气仔推送”获得资料&#xff08;专享优惠&#xff09; 模型简介 模型在 Matlab/Simulink仿真平台中搭建16节电芯锂电池电路模型&#xff0c;主要针对电动车锂电池组SOC差异性&#xff0c;采用模糊控制算法动态调节均衡电流&#xff0c;以减少均衡时间和能量损耗。…

换脸插件升级导致SDWebUI无法启动cannot import name ‘Undefined‘ from ‘pydantic.fields‘

今天在一台新的机器环境装了SDWEBUI&#xff0c;都使用最新的版本&#xff0c;升级了下换脸的插件&#xff0c;于是乎启动崩溃了。错误如下 Launching Web UI with arguments: --listen --skip-torch-cuda-test --disable-nan-check --skip-version-check --skip-python-versi…

SQL嵌套查询和集合查询

嵌套查询 先导概念 查询块&#xff1a;一个select语句为一个查询块 嵌套查询&#xff1a;将一个查询块嵌套在一个另一个查询块中where子句中的查询叫做嵌套查询。 嵌套查询的种类&#xff1a; 不相关子查询&#xff1a;子查询里的条件不依赖于父查询&#xff0c;从里到外依…

android布局

LinerLayout 权重分配的是剩余空间 RelativeLayout

Python脚本实现PC端大麦网自动购票(Selenium自动化测试工具)

文章目录 Selenium 简介Selenium webdriver 文档chromedriver&#xff08;谷歌浏览器驱动&#xff09;chromedriver 下载配置环境变量 大麦网购票脚本网页 dom 元素 启用远程调试&#xff08;操作已打开的窗口&#xff09; Selenium 简介 Selenium 是一个用于自动化测试的工具…

目标检测与追踪AI算法模型及边缘计算智能分析网关V4的算法应用

目标检测与追踪是计算机视觉领域中的一个重要任务&#xff0c;主要用于识别图像或视频中的目标&#xff0c;并跟踪它们的运动轨迹。针对这一任务&#xff0c;有许多先进的AI算法模型&#xff0c;例如&#xff1a; YOLO&#xff08;You Only Look Once&#xff09;&#xff1a;…
最新文章