首页 > 编程语言 >Java-19 深入浅出 MyBatis - 用到的设计模式 源码剖析 代理设计模式

Java-19 深入浅出 MyBatis - 用到的设计模式 源码剖析 代理设计模式

时间:2024-12-06 09:28:53浏览次数:6  
标签:Java 对象 代理 method Person 源码 Proxy 设计模式 public

点一下关注吧!!!非常感谢!!持续更新!!!

大数据篇正在更新!https://blog.csdn.net/w776341482/category_12713819.html

在这里插入图片描述

目前已经更新到了:

  • MyBatis(正在更新)

代理模式

概念介绍

代理模式(Proxy Pattern):给某一个对象提供一个代理,并由代理对象控制对原对象的引用,代理模式的英文名字叫 Proxy,它是一种对象结构型模式,代理模式分为静态代理和动态代理。

主要角色

  • 抽象主题(Subject):定义了真实对象和代理对象的共同接口,使得代理对象可以用在任何需要真实对象的地方。
  • 真实主题(RealSubject):实现了抽象主题接口,是真正执行请求的对象。
  • 代理(Proxy):实现了抽象主题接口,内部包含对真实主题的引用。代理对象控制对真实对象的访问,并可以在访问前后执行额外的操作。

代理模式的分类

远程代理(Remote Proxy)

为位于不同地址空间的对象提供本地代理,通过代理与远程对象进行通信。
示例:RMI(Remote Method Invocation)。

虚拟代理(Virtual Proxy)

用于创建开销较大的对象,只有在真正需要时才创建该对象。
示例:图像加载器延迟加载图片。

保护代理(Protection Proxy)

控制对真实对象的访问权限,根据访问者的权限执行不同操作。
示例:文件权限管理。

智能引用代理(Smart Reference Proxy)

在访问真实对象时进行额外操作,例如计数、日志记录、缓存等。

代理模式的优点

  • 职责分离: 通过代理控制访问,可以将额外的职责(如安全性、日志记录)从真实对象中剥离出来。
  • 增强功能: 在访问真实对象时,代理可以动态添加功能。
  • 性能优化: 通过虚拟代理延迟加载,提升性能。

代理模式的缺点

  • 增加复杂性: 由于引入了代理类,导致类的数量增加,系统复杂度提升。
  • 性能问题: 某些场景下,代理可能增加系统的开销,尤其是远程代理。

编写代码

Person

创建一个抽象类,Person 接口,有一个 doSomething 的方法。

package icu.wzk.proxy;

public interface Person {
    void doSomething();
}

Bob

package icu.wzk.proxy;

public class Bob implements Person {

    @Override
    public void doSomething() {
        System.out.println("Bob do something!");
    }
}

JdkDynamicProxy

package icu.wzk.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class JdkDynamicProxy implements InvocationHandler {

    private Person target;

    public JdkDynamicProxy(Person person) {
        this.target = person;
    }

    public Person getTarget() {
        return (Person) Proxy.newProxyInstance(
                target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                this
        );
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("Before calling " + method.getName());
        Person result = (Person) method.invoke(target, args);
        System.out.println("After calling " + method.getName());
        return result;
    }
}

JdkDynamicProxyTest

package icu.wzk.proxy;

public class JdkDynamicProxyTest {

    public static void main(String[] args) {
        Person bob = new Bob();
        bob.doSomething();
        System.out.println("========================");
        Person bob2 = new Bob();
        JdkDynamicProxy jdkDynamicProxy = new JdkDynamicProxy(bob2);
        Person proxyBob = jdkDynamicProxy.getTarget();
        proxyBob.doSomething();
    }

}

MyBatis 的体现

代理模式可以认为是 MyBatis 的核心使用的模式,正是因为这个模式的存在,我们只需要编写 Mapper 接口,不需要具体的实现,由 MyBatis 后台帮我们完成 SQL 的执行。
当我们使用 Configuration 的 getMapper 方法时,会调用 mapper.Registry.getMapper 方法,而该方法又会调用 mapperProxyFactory.newInstance(sqlSession) 来生成一个具体的代理:

import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class MapperProxyFactory<T> {
    private final Class<T> mapperInterface;
    private final Map<Method, MapperMethod> methodCache = new ConcurrentHashMap<>();

    // Constructor
    public MapperProxyFactory(Class<T> mapperInterface) {
        this.mapperInterface = mapperInterface;
    }

    // Getter for mapperInterface
    public Class<T> getMapperInterface() {
        return mapperInterface;
    }

    // Getter for methodCache
    public Map<Method, MapperMethod> getMethodCache() {
        return methodCache;
    }

    // Create a new instance of the proxy
    @SuppressWarnings("unchecked")
    protected T newInstance(MapperProxy<T> mapperProxy) {
        return (T) Proxy.newProxyInstance(
                mapperInterface.getClassLoader(),
                new Class[]{mapperInterface},
                mapperProxy
        );
    }

    // Create a new instance of the mapper with a given SqlSession
    public T newInstance(SqlSession sqlSession) {
        final MapperProxy<T> mapperProxy = new MapperProxy<>(sqlSession, mapperInterface, methodCache);
        return newInstance(mapperProxy);
    }
}

在这里,通过 newInstance(SqlSession sqlSession)方法会得到一个 MapperProxy对象,然后调用 T newInstance(MapperProxy mapperProxy)生成代理对象然后返回,下面是 MapperProxy 的代码:

public class MapperProxy<T> implements InvocationHandler, Serializable {

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        try {
            // 如果是Object类中的方法,直接调用
            if (Object.class.equals(method.getDeclaringClass())) {
                return method.invoke(this, args);
            }
            // 如果是默认方法,使用invokeDefaultMethod处理
            else if (isDefaultMethod(method)) {
                return invokeDefaultMethod(proxy, method, args);
            }
        } catch (Throwable t) {
            // 将异常包装并抛出
            throw ExceptionUtil.unwrapThrowable(t);
        }

        // 获取缓存的MapperMethod对象并执行
        final MapperMethod mapperMethod = cachedMapperMethod(method);
        return mapperMethod.execute(sqlSession, args);
    }
}

该 MapperProxy 实现了 InvocationHandler 接口,并实现了该接口的 invoke 方法,通过这种方式,我们需要编写 Mapper 接口类,当真正执行一个 Mapper 接口的时候,会转发给 MapperProxy.invoke 方法,而该方法则会调用后续的preparedStatement 等一系列方法,完成 SQL 的执行和返回。

标签:Java,对象,代理,method,Person,源码,Proxy,设计模式,public
From: https://blog.csdn.net/w776341482/article/details/144281531

相关文章

  • c#和 .net 类似于 java 和spring吗?
    是的,C#和.NET确实与Java和Spring有一些类似之处,它们在各自的生态系统中提供类似的功能和架构支持。以下是它们的对应关系和差异点:C#和Java的比较语言层面C#是一种由微软开发的现代化编程语言,语法风格与Java非常相似(两者都受C/C++的影响)。Java是一种跨......
  • 【关注可白嫖源码】基于微平台的学生公寓管理系统的设计与实现
    摘 要本论文主要论述了如何使用java的SSM框架开发一个学生公寓管理系统,本系统将严格按照软件开发流程进行各个阶段的工作,采用B/S结构,面向对象编程思想进行项目开发。在引言中,作者将论述学生公寓管理系统的当前背景以及系统开发的目的,后续章节将严格按照软件开发流程,对系统......
  • 【关注可白嫖源码】springboot校园招聘平台与岗位推荐系统的设计与实现
     摘 要对企业人才求职招聘的管理进行改革创新是提高各个企业并使之良性正面发展的必经之途。随着科技水准对社会经济的愈发依赖以及世界发展的轨迹预测,更少的人力需求,以及简单快捷的管理方式是迈进信息管理现代化的重要指标值。一个完善的企业必然具备相应的且高效的求职招......
  • 医院招聘考试管理系统|Java|SSM|JSP| 前后端分离
     【重要1⃣️】前后端源码+万字文档+部署文档            【包含内容】【一】项目提供非常完整的源码注释【二】相关技术栈文档【三】源码讲解视频                     【其它服务】【一】可以提供远......
  • 医院远程诊断管理系统|Java|SSM|JSP| 前后端分离
    【重要1⃣️】前后端源码+万字文档+部署文档            【包含内容】【一】项目提供非常完整的源码注释【二】相关技术栈文档【三】源码讲解视频                     【其它服务】【一】可以提供远程......
  • 毕业设计-水果在线销售系统的设计与实现(案例分析)-附源码
    摘 要在信息飞速发展的今天,网络已成为人们重要的信息交流平台。水果公司每天都有大量的信息需要通过网络发布,为此,本人开发了一个基于B/S(浏览器/服务器)模式的水果在线销售系统。该系统以python编程语言、MySQL和前端UI等为开发技术,实现了添加、修改、查看、删除系统数据。......
  • 毕业设计-仓库管理系统源码+论文
    项目简介仓库管理系统是一个旨在提高仓库信息处理速度、规范处理流程、提升管理人员产出效益的软件解决方案。该系统通过集成多种功能,实现了对仓库管理的全面控制和优化。系统的主要功能包括:仓库管理:系统允许管理员对仓库信息进行管理,包括更改仓库区域信息、仓库名称,以及删......
  • 毕业设计-航空票务推荐系统源码+论文
    项目简介航空票务推荐系统是一个基于B/S架构的Web应用程序,旨在提高航空票务信息管理的效率和便捷性。系统主要分为管理员和用户两大操作权限,各自拥有不同的功能模块,以满足不同用户的需求。管理员权限下,系统提供了用户信息管理、公告信息管理、公告类型管理等核心功能,允许管理......
  • javascript语言
    不要相信手掌的纹路,要相信手攥成拳的力量。javascript是一种脚本语言,和java完全不同的语言特点:大括号表示代码块区分大小写结尾的分号可加可不加,如果一行上写多个语句时,必须加分号用来区分多个语句单行注释//多行注释/**/注意:外部脚本不能包含<script>标签在js文件......
  • 关于java中的过滤器(Filter)
    在学习SpringBoot中了解到了过滤器和拦截器,浅谈一下对这两个的认识,若有不足,烦请斧正!首先,过滤器是javaWeb中提供的,而拦截器是spring提供的,这篇主要讲解Filter。用法:过滤器允许开发者在请求到达Servlet之前或响应返回客户端之前执行一些预处理或后处理操作(例如登录校验、敏感......