手写Spring框架(四)

2023-10-30

逻辑梳理

这部分完成AOP部分。
先梳理AOP的步骤:
getBean()
getBean()方法作为入口,而后是几个关键的类。Context在前文都有提到,现在解释一下其他的类。

AdviseSupport:通知的工具类

  • 完成配置文件的解析
  • 将Advise和目标类的方法建立关系——通过map结构
Map<Method,Map<String,Advice>>

例如:
在这里插入图片描述

AopConfig:调用方法时,判断方法的名称是否符合切面规则,如果符合就要触发通知
Advice:该类包含的属性:aspect的实例、method的回调
JdkDynamicAopProxy:生成一个全新的,类字节码重组,用代码生成代码,在内存中编译,在内存中完成实例化,返回的新的代理类,和原始类处于同一个继承体系(可赋值给目标类,对于用户来说,是无感知的,但是实际上在内部完成了偷梁换柱)

骨架与填空

先从context入手,在对象实例化之后进行织入:
在这里插入图片描述
上面相当于搭好了骨架,接着分别填空。

    //从配置文件读取信息保存到config对象
    private PIGAdvisedSupport instantionAopConfig(PigBeanDefinition beanDefinition) {
        PIGAopConfig config = new PIGAopConfig();
        config.setPointCut(this.reader.getConfig().getProperty("pointCut"));
        config.setAspectClass(this.reader.getConfig().getProperty("aspectClass"));
        config.setAspectBefore(this.reader.getConfig().getProperty("aspectBefore"));
        config.setAspectAfter(this.reader.getConfig().getProperty("aspectAfter"));
        config.setAspectAfterThrow(this.reader.getConfig().getProperty("aspectAfterThrow"));
        config.setAspectAfterThrowingName(this.reader.getConfig().getProperty("aspectAfterThrowingName"));
        return new PIGAdvisedSupport(config);
    }

配置文件可能长这样:
在这里插入图片描述
PIGAdvisedSupport比较关键,它负责根据以上解析出来的config,将Advise和目标类的方法建立关系。
也就是config.setTargetClass(clazz);这个方法

public void setTargetClass(Class targetClass) {
        this.targetClass = targetClass;
        //解析表达式
        parse();
    }

    public Class getTargetClass() {
        return targetClass;
    }


    private void parse() {

        //对配置文件中的特殊字符进行转义
        String pointCut = config.getPointCut()
                .replaceAll("\\.","\\\\.")
                .replaceAll("\\\\.\\*",".*")
                .replaceAll("\\(","\\\\(")
                .replaceAll("\\)","\\\\)");

        // pointCut=public .* com.gupaoedu.vip.demo.service..*Service..*(.*)
        String pointCutForClassRegex = pointCut.substring(0,pointCut.lastIndexOf("\\(") - 4);
        //提取class的全名
        pointCutClassPattern = Pattern.compile("class " + pointCutForClassRegex.substring(pointCutForClassRegex.lastIndexOf(" ") + 1));

        try {
            //开始映射目标类方法和通知的关系
            methodCache = new HashMap<Method, Map<String, PIGAdvice>>();

            //开始匹配目标类的方法
            Pattern pointCutPattern = Pattern.compile(pointCut);

            //先把要织入的切面的方法缓存起来
            Class aspectClass = Class.forName(this.config.getAspectClass());
            Map<String,Method> aspectMethods = new HashMap<String, Method>();
            for (Method method : aspectClass.getMethods()) {
                aspectMethods.put(method.getName(),method);
            }

            //扫描目标类的所有的方法
            for (Method method : this.targetClass.getMethods()) {
                //包括了修饰符、返回值、方法名、形参列表
                String methodString = method.toString();
                //把异常去掉
                if(methodString.contains("throws")){
                    methodString = methodString.substring(0,methodString.lastIndexOf("throws")).trim();
                }

                Matcher matcher = pointCutPattern.matcher(methodString);
                if(matcher.matches()){
                    Map<String,PIGAdvice> advices = new HashMap<String, PIGAdvice>();

                    //前置通知
                    if(!(null == config.getAspectBefore() || "".equals(config.getAspectBefore()))){
                        advices.put("before",
                                new PIGAdvice(aspectClass.newInstance(),aspectMethods.get(config.getAspectBefore())));
                    }

                    //后置通知
                    if(!(null == config.getAspectAfter() || "".equals(config.getAspectAfter()))){
                        advices.put("after",
                                new PIGAdvice(aspectClass.newInstance(),aspectMethods.get(config.getAspectAfter())));
                    }

                    //异常通知
                    if(!(null == config.getAspectAfterThrow() || "".equals(config.getAspectAfterThrow()))){
                        advices.put("afterThrowing",
                                new PIGAdvice(aspectClass.newInstance(),aspectMethods.get(config.getAspectAfterThrow())));
                    }

                    methodCache.put(method,advices);
                }

            }


        }catch (Exception e){
            e.printStackTrace();
        }

    }

测试

这是用户侧的代码(切面):

@Slf4j
public class LogAspect {

    //在调用一个方法之前,执行before方法
    public void before(){
        //这个方法中的逻辑,是由我们自己写的
        log.info("Invoker Before Method!!!");
    }

    //在调用一个方法之后,执行after方法
    public void after(){
        log.info("Invoker After Method!!!");
    }

    public void afterThrowing(){
        log.info("出现异常");
    }

}

(请求):

@PIGRequestMapping("/query.json")
	public PIGModelAndView query(HttpServletRequest request, HttpServletResponse response,
								 @PIGRequestParam("name") String name){
		String result = queryService.query(name);
		return out(response,result);
	}

在这里插入图片描述

总结

在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

手写Spring框架(四) 的相关文章

随机推荐

  • 【Ei检索】2022年计算语言学和自然语言处理国际会议(CLNLP 2022)

    2022年计算语言学和自然语言处理国际会议 CLNLP 2022 重要信息 会议网址 www clnlp org 会议时间 2022年12月16 18日 召开地点 中国北京 截稿时间 2022年10月31日 录用通知 投稿后2周内 收录检索
  • GridView编辑删除操作

    第一种 使用DataSource数据源中自带的编辑删除方法 这种不常用 在这里就不加说明了 第二种 使用GridView的三种事件 GridView1 RowEditing 编辑 GridView1 RowUpdating 更新 GridV
  • 胡小明:城市大脑与人脑不同的数据意识

    一 数据应用要区别对待 1 2 数据应用比数据收集重要 大数据热正在席卷全国 许多地方政府都成立大数据局 统管政府的数据资源并将数据收集摆在第一位 数据应用研究却迟迟跟不上 投资不断增长应用效益却无相应增长 大数据收集已经得不偿失 应用效益
  • 【STM32】IAP

    首先先明白几个概念 IAP In applicating Programing 在应用编程 ICP In Circuit Programming 在线编程 我自己理解的话 ICP就是平时用仿真器直接下载程序的方式 应用程序直接从FLASH的
  • wireshark过滤规则

    wireshark是一款抓包软件 常用来分析网络底层协议 寻找网络安全问题 平时用的最多的是过滤功能 wireshark的过滤分功能有两种 抓包过滤器和显示过滤器 抓包过滤器的过滤规则分为四个部分 放行 类型 协议和逻辑运算符 方向 src
  • Jmeter性能测试面试基础问答

    性能测试基础 简述实施软件性能测试的流程 a 性能需求分析 挑选用户使用最频繁的功能来做测试 比如 登陆 搜索 提交订单 确定性能指标 比如 事务通过率为100 90 的事务响应时间不超过5秒 并发用户为1000人时CPU和内存的使用率在7
  • 自动化测试很难吗?是的,难。?

    其实现在软件测试有一个特别奇怪的现象 那就是每个人在一起进入这个圈子的时候 他想的就是我要自动化测试 我要学会自动化 自动化会替换手工测试 很多这种心声 我在这给大家来分析一下 首先为什么很多人在入这个圈的时候 会听到 这种声音 比如 学好
  • C语言例题讲解(if语句,循环语句,函数)

    目录 if语句例题 题目分析 代码 题目总结 循环语句例题 题目分析 代码 题目总结 函数例题 题目分析 代码 题目总结 if语句例题 计算1 1 1 2 1 3 1 4 1 5 1 99 1 100 的值 打印出结果 题目分析 1 首先我
  • LinkList集合详解

    LinkList集合详解 1 LinkedList简介 LinkedList类是一个继承于AbstractSequentialList的双向循环链表 它是非同步的 也是非线程安全的 LinkedList实现了List接口 能对它进行队列操作
  • 在elementUI中sort-orders排序,默认为三种,怎么改成两种

    在 table表单中添加sort change事件 sort orders ascending descending
  • 解决:同样的Python程序,在cmd和pycharm都能正常运行,但是在Visual Studio Code却报错,且`conda activate`命令无法激活或切换虚拟环境

    解决 同样的Python程序 在cmd和pycharm都能正常运行 但是在Visual Studio Code却报错 且 conda activate 命令无法激活或切换虚拟环境 1 软件环境 2 问题描述 3 解决方法 4 结果预览 1
  • Linux 文本处理工具 - sed(用于过滤和转换文本)

    Linux 文本处理工具 sed 用于过滤和转换文本 文章目录 Linux 文本处理工具 sed 用于过滤和转换文本 一 简介 二 常用参数 三 动作说明 四 实例 p 显示 d 删除 a 添加 c 替换 w 把符合的行写到指定文件中 i
  • Code-server 云服务器配置docker 运行

    Code server 云服务器配置docker 运行 1 docker安装 安装需要的软件包 yum utils device mapper persistent data lvm2 yum install y yum utils dev
  • android httpClient 支持HTTPS的2种处理方式

    问题 项目中Android https或http请求地址重定向为HTTPS的地址 相信很多人都遇到了这个异常 无终端认证 javax net ssl SSLPeerUnverifiedException No peer certificat
  • Redis学习笔记

    目录 一 redis前言 1 1 Redis简介 1 2 主要特点 1 3redis 的windows安装后 1 4 修改Redis配置文件 二 redis常用数据类型 三 redis常用命令 1 字符串操作命令 2 哈希操作命令 3 列表
  • python爬虫,wallhaven热门壁纸多线程采集下载源码

    新年新气象 祝大家牛转乾坤 牛气冲天 过年期间收到了很多朋友的新年祝福 没有一一回应 见谅 很久没写爬虫了 手生了 在吾爱找了一个练手网站 国外的壁纸网站 wallhaven 这里采集下载热门图片为例 重温一下python图片爬虫 感兴趣的
  • Veeam 备份还原操作手册

    目录 一 安装Bakup Replication 1 1 选择 Backup Replication 1 2 选择Install安装 二 添加VC主机 2 1 VMWARE VSPHERE 添加 2 2 VC主机名 2 3 用户认证 三 配
  • Linux I/O多路复用——epoll模型实现服务端Socket通信

    目录 epoll模型 epoll函数 epoll create epoll ctl epoll wait 程序流程 水平触发 LT 边沿触发 ET select poll epoll对比 为什么ET模式下 需要将套接字设置为非阻塞式 epo
  • C语言_指针

    C语言指针 指针 这个要从直接访问与间接访问说起 在程序中一般通过变量名来引用变量的值 程序通过编译后就会把变量名转化为变量的地址 通过地址对数据进行存取操作 这种方式称为直接访问 而间接访问是将变量i的地址存放在另一变量中 然后通过该变量
  • 手写Spring框架(四)

    逻辑梳理 这部分完成AOP部分 先梳理AOP的步骤 getBean 方法作为入口 而后是几个关键的类 Context在前文都有提到 现在解释一下其他的类 AdviseSupport 通知的工具类 完成配置文件的解析 将Advise和目标类的