自定义实现spring源码

news2024/11/18 11:26:40

目录

1.本文实现目标

2.自定义注解

3. 定义controller加上自定义的注释

4. 识别到这个注解

5.扫描目录,返回该目录下所有文件名(全限定名)

6.扫描该文件所在包中所有带这两个注解的类和方法放到map中

7.通过反射的方式创建实例

8.通过exec方法调动实例,执行实例中的方法

9.执行结果


1.本文实现目标

  •  自定义注解
  • 识别到这个注解
  • 通过反射的方式创建实例
  • 通过exec方法调动实例,执行实例中的方法

2.自定义注解

详见:自定义注解(Annontation)_qq_52240237的博客-CSDN博客

import java.lang.annotation.*;

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @ interface Controller {
}
import java.lang.annotation.*;

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.METHOD})
public @interface RequestMapping {
    /**
     *
     * @return
     */
    String value() default "";
}

3. 定义controller加上自定义的注释

@Controller
@RequestMapping("test")
public class TestController {
    @RequestMapping
    public  String index(){
        System.out.println("这里是test类");
        return "";
    }
    @RequestMapping("index1")
    public  String index1(){
        System.out.println("这里是test类的index1方法");
        return "";
    }
}

4. 识别到这个注解

private static boolean isController(Class cl){

    Annotation annotation = cl.getAnnotation(Controller.class);
    if(annotation!=null){
        return  true;
    }
    return false;
}
private static boolean isRequestMapping(Class cl){
    Annotation annotation = cl.getAnnotation(RequestMapping.class);
    if(annotation!=null){
        return  true;
    }
    return false;
}
private  static boolean isRequestMapping(Method method){
    Annotation annotation = method.getAnnotation(RequestMapping.class);
    if(annotation!=null){
        return  true;
    }
    return false;
}
private static RequestMapping getRequestMapping(Class cl){
    Annotation annotation = cl.getAnnotation(RequestMapping.class);
    if(annotation instanceof  RequestMapping){
        return  (RequestMapping) annotation;
    }
    return null;
}
private static RequestMapping getRequestMapping(Method method){
    Annotation annotation = method.getAnnotation(RequestMapping.class);
    if(annotation instanceof  RequestMapping){
        return  (RequestMapping) annotation;
    }
    return null;
}

5.扫描目录,返回该目录下所有文件名(全限定名)

private static List<String> traverseFolder2(String path) {
    File file = new File(path);
    List<String> classFiles=new ArrayList<>();
    if (file.exists()) {
        LinkedList<File> list = new LinkedList<File>();
        File[] files = file.listFiles();
        for (File file2 : files) {
            if (file2.isDirectory()) {
                list.add(file2);
            } else {
                classFiles.add(file2.getAbsolutePath());
            }
        }
        File temp_file;
        while (!list.isEmpty()) {
            temp_file = list.removeFirst();
            //.listFiles():该目录中的文件和目录
            files = temp_file.listFiles();
            for (File file2 : files) {
                //.isDirectory():检查该目录是不是一个标准文件夹
                if (file2.isDirectory()) {
                    list.add(file2);
                } else {
                    //.getAbsolutePath():返回抽象路径名的绝对路径名字符串
                    classFiles.add(file2.getAbsolutePath());
                }
            }
        }
    } else {

    }
    return classFiles;
}

6.扫描该文件所在包中所有带这两个注解的类和方法放到map中

private static HashMap<String, Map<String,Method>> map=new HashMap<>();
private static HashMap<String, Object> objMap=new HashMap<>();
public static void scanner(String path,String packageName){
    List<String> paths = traverseFolder2(path);
    for (String p : paths) {
        p=p.substring(path.length()-1);
        try {
            String className=packageName+"."+p.replaceAll( Matcher.quoteReplacement(File.separator),".");
            String replace = className.replace(".class", "");
            Class<?> cl = ClassLoader.getSystemClassLoader().loadClass(replace);
            if(isController(cl)){
                if(isRequestMapping(cl)){
                    RequestMapping requestMapping = getRequestMapping(cl);
                    if(map.containsKey(requestMapping.value())){
                        throw  new RuntimeException("类多注解值:"+requestMapping.value());
                    }else {
                        map.put(requestMapping.value(),new HashMap<>());
                        objMap.put(requestMapping.value(),cl.newInstance());
                    }
                    Method[] declaredMethods = cl.getDeclaredMethods();
                    for (Method declaredMethod : declaredMethods) {
                        if(isRequestMapping(declaredMethod)){
                            RequestMapping mapping = getRequestMapping(declaredMethod);
                            if(map.get(requestMapping.value()).containsKey(mapping.value())){
                                throw  new RuntimeException("方法多注解值:"+requestMapping.value());
                            }else {
                                map.get(requestMapping.value()).put(mapping.value(),declaredMethod);
                            }
                        }
                    }
                }else {
                    throw  new RuntimeException("类无requestMapping");
                }
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }
    }


}

7.通过反射的方式创建实例

private static HashMap<String, Map<String,Method>> map=new HashMap<>();
private static HashMap<String, Object> objMap=new HashMap<>();
public static void exec(String classPath,String methodPath){
    if(objMap.get(classPath)==null){
        System.out.println("没有这个类 404");
    }else {
        if(map.get(classPath).get(methodPath)==null){
            System.out.println("没有这个方法 404");
        }else {
            try {
                map.get(classPath).get(methodPath).invoke(objMap.get(classPath));
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        }
    }
}

8.通过exec方法调动实例,执行实例中的方法

public class Main {
    static {
        //在当前调用类所在的同一路径下查找该fileName文件
        String path = Main.class.getResource("").getPath();
        //返回此类的包的名字
        String packageName = Main.class.getPackage().getName();
        HeaboyMvc.scanner(path,packageName);
    }

    public static void main(String[] args) {
        HeaboyMvc.exec("","");
        HeaboyMvc.exec("test","index1");
        HeaboyMvc.exec("test","");
        System.out.println("Hello World!");
    }
}

9.执行结果

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Java】智慧工地管理系统源码(SaaS模式)

智慧工地是聚焦工程施工现场&#xff0c;紧紧围绕人、机、料、法、环等关键要素&#xff0c;综合运用物联网、云计算、大数据、移动计算和智能设备等软硬件信息技术&#xff0c;与施工生产过程相融合。 一、什么是智慧工地 智慧工地是指利用移动互联、物联网、智能算法、地理信…

汉字形近字(OCR)

近期做中文OCR识别的优化&#xff0c;抓破头皮却收获甚微。 为了百尺竿头更进一步&#xff0c;遂将目光聚焦在中文汉字特有的形近字和生僻字问题上&#xff0c;于是怒发整理形近字大全&#xff08;花了不少刀&#xff09;&#xff0c;希望对同行朋友们也有帮助&#xff1a; 地表…

Vue + Cesium快速搭建(无需配置)

方式一&#xff1a;直接引入&#xff08;最简单&#xff09; 1.安装Cesium&#xff08;Vue搭建可以看我上一期的文章&#xff09; npm i cesium -save2.将node_modules\cesium\Build\Cesium文件夹拷贝到项目的public文件中 3.在public\index.html引入Cesium <!DOCTYPE h…

把天气美景“搬”进HarmonyOS桌面里是种怎样的体验

近日&#xff0c;在HDC 2023大会上&#xff0c;HarmonyOS 4正式官宣。其中&#xff0c;全新的全景天气壁纸延续桌面天气组件、天气AOD熄屏显示便捷、易用等特点&#xff0c;为用户带来感受真实天气的视野体验&#xff0c;受到了广泛的关注。 日常中&#xff0c;多变的天气影响…

【LeetCode】313. 超级丑数

313. 超级丑数 方法&#xff1a;“多路归并” 思路 这道题其实是 264. 丑数 II 的进阶&#xff0c;前者固定使用三个指针&#xff0c;分别对应于 2、3、5&#xff0c;而这道的primes数组长度不固定&#xff0c;因此使用指针数组来对应 primes 的每一个值。 第一个丑数一定是 …

MySQL的Group_concat函数超过1024怎么破?

最近在MySQL写字段拼接&#xff0c;结果发现拼接的不完整。 丢失了一般的字段。查询了一下才发现。 group_concat长度限制默认是1024&#xff0c;如果在实际使用过程中拼接好的字符串长度超过了最大长度&#xff0c;那么最后仅保留前1024个字符。 执行SQL SHOW VARIABLES LIK…

线上影院售票系统票商端H5小程序源码搭建

搭建一个线上影院售票系统票商端H5小程序源码是一个相对复杂的过程&#xff0c;需要涉及到前端开发、后端开发以及数据库的搭建等多个方面。具体步骤如下&#xff1a; 1. 确定需求&#xff1a;首先需要明确影院售票系统的功能需求&#xff0c;包括电影信息的展示、影院排片管理…

开发中的花样玩法(前端打工人须知)

一、关于vue使用vant的van-popup&#xff0c;子元素设定固定定位失效问题。 position: fixed; 原因是该组件使用了transform导致&#xff0c;父元素使用了transform会导致子元素在使用固定定位时失效&#xff0c;解决方法就是把要设置固定定位的子元素放在跟组件平级的位置&…

PHP流浪动物招领网站mysql数据库web结构apache计算机软件工程网页wamp

一、源码特点 PHP流浪动物招领网站 是一套完善的web设计系统&#xff0c;对理解php编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。 下载链接 nullhttps://download.csdn.net/download/qq_41221322/88190168视频演示 …

狂码三万字 | 三维场景点云理解与重建技术

目录 00 引言 01 点云特征提取与匹配 1.1 传统点云特征提取 1.2 点云深度学习 1.3 点云卷积 1.4 稀疏卷积 1.5 点云Transformer 1.6 点云旋转不变特征提取 1.7 点云匹配 02 场景点云语义分割 2.1 场景表征与数据集 2.1.1 室内场景表征与相关数据集 2.1.2 室外场…

motrix配合百度网盘的下载激活使用,需下载Motrix(官网)绝对安全

使用文档下载 需要下载神器motrix 有官网怕被和谐就不挂了放在上面文档里,也可baidu自行搜索 motrix下载 操作步骤 --> 简单易学↓↓↓↓ 网盘链接和提取码分开来填,操作见下图↓↓ 就是加速(点这儿解析链接) 点击后有时需要等待几秒钟 如果没…

完整版:TCP、UDP报文格式

目录 TCP报文格式 报文格式 报文示例 UDP报文格式 报文格式 报文示例 TCP报文格式 报文格式 图1 TCP首部格式 字段长度含义Source Port16比特源端口&#xff0c;标识哪个应用程序发送。Destination Port16比特目的端口&#xff0c;标识哪个应用程序接收。Sequence Numb…

安防视频监控汇聚EasyCVR平台接入Ehome告警,公网快照不显示的原因排查

智能视频监控汇聚平台TSINGSEE青犀视频EasyCVR可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等&#xff0c;以及支持厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等&#xff0c;视频监控管理平台…

外贸接单购物网站java开源搭建--内置客服系统+后台采集功能

搭建一个外贸接单购物网站是一个具有挑战的任务&#xff0c;需要考虑到用户界面设计、后端系统开发、客服系统和采集功能等多个方面。下面是一个大致的开发计划。 1. 用户界面设计 - 设计一个直观易用的用户界面&#xff0c;包括用户注册、登录、商品展示、下单等功能。 …

Scratch 之 3D 介绍及教程

第一章 为什么 3D 很难&#xff1f; 1.1 3D 难在何处&#xff1f; 3D 之所以会使我们觉得困难&#xff0c;是因为 Scratch 软件只有两个坐标轴&#xff0c;既&#xff1a;X轴、Y轴。 2维坐标系 而 3D 却拥有三个坐标轴&#xff1a; 3维坐标系 怎么办&#xff1f;很简单&…

Leetcode-每日一题【剑指 Offer 12. 矩阵中的路径】

题目 单词必须按照字母顺序&#xff0c;通过相邻的单元格内的字母构成&#xff0c;其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。 例如&#xff0c;在下面的 34 的矩阵中包含单词 "ABCCED"&#xff08;单词中的字母…

空天地光网络

空天地光网络 星座 卫星星座分类可参考卫星导航 walker星座&#xff1a; a classical inclined orbit constellation consisting of many orbits with the same height, and inclination. 参考论文Load-Balanced Virtual Network Embedding Based on Deep Reinforcement L…

Ariadne’s Thread-使用文本提示改进对感染区域的分割胸部x线图像

论文&#xff1a;https://arxiv.org/abs/2307.03942&#xff0c; Miccai 2023 代码&#xff1a;GitHub - Junelin2333/LanGuideMedSeg-MICCAI2023: Pytorch code of MICCAI 2023 Paper-Ariadne’s Thread : Using Text Prompts to Improve Segmentation of Infected Areas fro…

[保研/考研机试] KY129 简单计算器 浙江大学复试上机题 C++实现

描述 读入一个只包含 , -, *, / 的非负整数计算表达式&#xff0c;计算该表达式的值。 输入描述&#xff1a; 测试输入包含若干测试用例&#xff0c;每个测试用例占一行&#xff0c;每行不超过200个字符&#xff0c;整数和运算符之间用一个空格分隔。没有非法表达式。当一行中…

聪明灵犀:智能AI对话问答工具

这是一款功能强大的人工智能软件&#xff0c;支持ai智能对话与聊天。简单输入问题&#xff0c;即可快速获取相应答案&#xff0c;能够帮助用户快速生成各类文章&#xff0c;内容连贯、结构完整&#xff0c;能够满足用户的写作需求&#xff0c;有效提高写作效率。具备广泛的知识…