【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动态代理创建代理类。

相关推荐
每天进步一点_JL4 分钟前
Docker 是什么?
后端·docker·容器
app出海创收老李12 分钟前
海外独立创收日记(4)-第一笔汇款
前端·后端·程序员
咕白m62522 分钟前
Python 将 Excel 转换为图片:实现数据可视化
后端·python
蓑笠翁0011 小时前
Django REST Framework 全面指南:从模型到完整API接口开发
后端·python·django
鸽鸽程序猿1 小时前
【项目】基于Spring全家桶的论坛系统 【下】
后端·spring·restful
IT_陈寒1 小时前
Redis性能优化:5个被低估的配置项让你的QPS提升50%
前端·人工智能·后端
radient2 小时前
初识Agent、Prompt、Function Coding、MCP
后端·程序员·架构
Lisonseekpan2 小时前
Spring Boot 中使用 Caffeine 缓存详解与案例
java·spring boot·后端·spring·缓存
SimonKing2 小时前
分布式日志排查太头疼?TLog 让你一眼看穿请求链路!
java·后端·程序员
小许学java2 小时前
Spring AI快速入门以及项目的创建
java·开发语言·人工智能·后端·spring·ai编程·spring ai