【SpringBoot系列】动态代理为接口增加实现,一文搞定Spring data 原理,你也可以这样玩!

好久不写,也是真写不下去,不知道为啥,总是开始想写,一会就失去了动力。

今天无论如何整一篇吧,总结下JPA的原理,也为以后做同样的设计做个初稿。

1、jpa的使用

CSDN之前写了两篇Spring data JPA 的使用,可以参考下怎么用的,好用且简单,传送门

blog.csdn.net/perfect2011...

blog.csdn.net/perfect2011...

2、spring data 的特点

强大的存储库和自定义对象映射抽象

从存储库方法名称派生动态查询

实现域基类提供基本属性

无论是哪种持久化存储, 数据访问对象通常都会提供对单一域对象的CRUD (创建、读取、更新、删除)操作、查询方法、排序和分页方法等。Spring Data则提供了基于这些层面的统一接口(CrudRepository,PagingAndSortingRepository)以及对持久化存储的实现。

3、jpa的简单使用

为了能够简单实现JPA,也为了能说明技术特点,还是写一个简单的JPA使用,具体的实现代码可以看上面两个链接

3.1 jpa简单使用

entity定义

kotlin 复制代码
import jakarta.persistence.*;
import lombok.Data;
 
import java.io.Serializable;
 
@Entity
@Data
@Table(name = "t_user")
public class UserEntity implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    @Column(name = "username")
    private String userName;
    @Column(name = "password")
    private String password;
}

repo的定义

kotlin 复制代码
import com.alicp.jetcache.anno.CacheType;
import com.alicp.jetcache.anno.Cached;
import com.xin.jetcachetest.entity.UserEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
 
public interface UserRepo extends JpaRepository<UserEntity, Integer>, JpaSpecificationExecutor<UserEntity> {
 
    UserEntity findAllByUserName(String userName);
}

项目中使用

kotlin 复制代码
import com.xin.jetcachetest.cache.UserRepo;
import com.xin.jetcachetest.entity.UserEntity;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
 
@RestController
public class TestController {
    @Resource
    UserRepo userRepo;
    @GetMapping("/user")
    public UserEntity getUser(){
        UserEntity allByUserName = userRepo.findAllByUserName("admin");
        return allByUserName;
    }
}

简单总结要点:

  • 1、有entity定义
  • 2、创建访问repo 实现相关的接口
  • 3、在其他地方使用
  • 4、简单实现-原理 整个JPA的使用还是很简单的,这里的技术实现是怎么样的,主要

实现方式,在以后的工作中可以使用类似的开发技术方案,我关注的两个点

1.接口是怎么有实现的?

2.动态sql 是怎么做到的?

这两者的基础都是Java的动态代理,下面来个简单实现,万变不离其宗,我们来接管这个接口的实现。

4.1 自己实现一个repo

这里直接选择了一个CrudRepository 进行实现,同时也只实现了一个findById接口,在内容里加了一个打印

很简单,这里只是作为demo,没有真正的实现接口

4.2 实现代理接口

java 复制代码
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
 
public class RepoProxy implements InvocationHandler {
 
    private Object target;
    private XinRepository xinRepository;
 
    public RepoProxy() {
        xinRepository = new XinRepository();
    }
 
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Method method1 = xinRepository.getClass().getMethod(method.getName(), method.getParameterTypes());
        return method1.invoke(xinRepository,args);
    }
}

这里的重点是将代理方法的调用直接转接到XinRepository中调用,相当于狸猫换太子

4.3 测试

直接通过动态代理创建代理类。

arduino 复制代码
import com.xin.jetcachetest.cache.UserRepo;
 
import java.lang.reflect.Proxy;
 
public class Aain {
    public static void main(String[] args) {
 
        UserRepo userRepo = (UserRepo) Proxy.newProxyInstance(UserRepo.class.getClassLoader(), new Class[]{UserRepo.class}, new RepoProxy());
        userRepo.findById(1);
    }
}

4.4 看下结果

总结

原理很简单,将接口生成动态代理,然后在代理中将方法转换到对应的实现中。

UserRepo 继承相关的接口

XinRepository 也要实现UserRepo 继承的接口,也就是保持接口中方法一致

RepoProxy 代理所有的接口方法,转入实现类XinRepository中

使用JDK动态代理创建代理类。

相关推荐
جيون داد ناالام ميづ1 小时前
Spring Boot 核心原理(五):配置管理怎么玩?从基础到多环境再到配置中心
java·spring boot·后端
_小九1 小时前
【开源】耗时数月、我开发了一款功能全面【30W行代码】的AI图床
前端·后端·开源
疯狂的程序猴1 小时前
完整指南:iPhone崩溃日志查看与分析方法及低内存崩溃处理
后端
秧歌star5191 小时前
PageHelper 分页失效原因分析与正确实践
后端
疯狂的程序猴2 小时前
苹果iOS应用签名与上架App Store完整指南包括注意事项
后端
回家路上绕了弯2 小时前
生产环境服务器变慢?从应急到根因的全流程诊断处理指南
分布式·后端
小胖霞2 小时前
Node+Express+MySQL 后端生产环境部署,实现注册功能(三)
前端·后端
aiopencode2 小时前
抓包技术全面指南:原理、工具与应用场景
后端
该用户已不存在2 小时前
Gemini 3.0 发布,Antigravity 掀桌,程序员何去何从?
后端·ai编程·gemini
aiopencode2 小时前
软件苹果商城上架的流程与团队协作模式 一个项目从开发到发布的完整经历
后端