【Spring Data JPA 系列】09、深入理解原理

10、原理

10.1、Repository原理

核心机制:动态代理

  1. JdkDynamicAopProxy—invoke
  • 调用 JPA的Repository统一实现

    • SimpleJpaRepository

    • 就是去通过JPA的API完成持久化操作

手写代码进行测试:

源码分析:

 package com.yykk.sourcecode;
 
 import com.yykk.config.SpringDataJPAConfig;
 import com.yykk.repositories.CustomerRepository;
 import org.springframework.context.annotation.AnnotationConfigApplicationContext;
 import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
 
 import javax.persistence.EntityManager;
 import java.lang.reflect.ParameterizedType;
 import java.lang.reflect.Proxy;
 import java.lang.reflect.Type;
 
 public class SourceCode {
     public static void main(String[] args) throws ClassNotFoundException {
         // spring上下文  spring容器 --- ioc加载过程:创建所有的bean,报错repository的Bean
         AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringDataJPAConfig.class);
 
         //CustomerRepository repository = context.getBean(CustomerRepository.class);
 
         //System.out.println(repository.getClass()); // jdk 动态代理
 
         //Optional<Customer> byId = repository.findById(7L);
 
         //System.out.println(byId.get());
 
         // 获得entityManager
         LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = context.getBean(LocalContainerEntityManagerFactoryBean.class);
         EntityManager nativeEntityManager = entityManagerFactoryBean.createNativeEntityManager(null);
 
         // 获得当前接口的pojo类
         // getGenericInterfaces() 拿到当前接口的父接口 = PagingAndSortingRepository
         ParameterizedType parameterizedType = (ParameterizedType)CustomerRepository.class.getGenericInterfaces()[0];
         // 拿到接口的泛型 = <Customer,Long>
         Type type = parameterizedType.getActualTypeArguments()[0];
         Class clazz = Class.forName(type.getTypeName());
 
         CustomerRepository repository = (CustomerRepository) Proxy.newProxyInstance(
                 CustomerRepository.class.getClassLoader(),
                 new Class[]{CustomerRepository.class},
                 new MyJpaRepository(nativeEntityManager,clazz)
         );
         repository.findById(7L);
     }
 }
复制代码
 package com.yykk.sourcecode;
 
 import javax.persistence.EntityManager;
 import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Method;
 
 public class MyJpaRepository implements InvocationHandler {
 
     EntityManager entityManager;
     Class pojoClass;
 
     public MyJpaRepository(EntityManager entityManager, Class pojoClass) {
         this.entityManager = entityManager;
         this.pojoClass = pojoClass;
     }
 
     // method 当前调用的方法
     // args 当前调用方法的参数
     @Override
     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
 
         // jpa的统一实现类
         MyJpaProxy myJpaProxy = new MyJpaProxy(entityManager, pojoClass);
         Method targetMethod = myJpaProxy.getClass().getMethod(method.getName(), method.getParameterTypes());
 
         return targetMethod.invoke(myJpaProxy,args);
     }
 }
复制代码
 package com.yykk.sourcecode;
 
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.Pageable;
 import org.springframework.data.domain.Sort;
 import org.springframework.data.repository.PagingAndSortingRepository;
 
 import javax.persistence.EntityManager;
 import java.util.Optional;
 
 public class MyJpaProxy implements PagingAndSortingRepository {
 
     EntityManager entityManager;
     Class pojoClass;
 
     public MyJpaProxy(EntityManager entityManager, Class pojoClass) {
         this.entityManager = entityManager;
         this.pojoClass = pojoClass;
     }
 
     @Override
     public Iterable findAll(Sort sort) {
         return null;
     }
 
     @Override
     public Page findAll(Pageable pageable) {
         return null;
     }
 
     @Override
     public Object save(Object entity) {
         return null;
     }
 
     @Override
     public Iterable saveAll(Iterable entities) {
         return null;
     }
 
     @Override
     public Optional findById(Object id) {
         // JPA
         return Optional.of(entityManager.find(pojoClass,id));
     }
 
     @Override
     public boolean existsById(Object o) {
         return false;
     }
 
     @Override
     public Iterable findAll() {
         return null;
     }
 
     @Override
     public Iterable findAllById(Iterable iterable) {
         return null;
     }
 
     @Override
     public long count() {
         return 0;
     }
 
     @Override
     public void deleteById(Object o) {
 
     }
 
     @Override
     public void delete(Object entity) {
 
     }
 
     @Override
     public void deleteAllById(Iterable iterable) {
 
     }
 
     @Override
     public void deleteAll(Iterable entities) {
 
     }
 
     @Override
     public void deleteAll() {
 
     }
 }
复制代码
 package com.yykk.sourcecode;
 
 import com.yykk.config.SpringDataJPAConfig;
 import com.yykk.pojo.Customer;
 import com.yykk.repositories.CustomerRepository;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
 import org.springframework.test.context.ContextConfiguration;
 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
 
 import java.util.Optional;
 
 @EnableJpaRepositories(basePackages = "com.yykk.repositories")
 @ContextConfiguration(classes = SpringDataJPAConfig.class)
 @RunWith(SpringJUnit4ClassRunner.class)
 public class SpringDataJpaSource {
 
     @Autowired
     CustomerRepository repository;
 
     @Test
     public void test_source() {
         Optional<Customer> id = repository.findById(7L);
         System.out.println(id.get());
     }
 }
复制代码

源码学习文章:

www.dewafer.com/2016/05/09/…

10.2、spring整合JPA原理

1、spring怎么管理Repository(怎么创建的Repository的Bean)

  1. @EnableJpaRepositories(basePackages = "com.yykk.repositories")
  2. spring容器启动的时候ioc容器加载 ,根据 com.yykk.repositories 去创建bean

2、spring怎么将动态代理创建bean

 Exceptioninthread"main"org.springframework.beans.factory.NoSuchBeanDefinitionException:No qualifying bean of type ' com.yykk.repositories.CustomerRepository' available
复制代码
  1. 没有找到bean,解决思路:

    • 应用层面:是不是配置不正确,配置正确,排除!
    • 底层层面:是不是spring底层扫描-排除。(Bean—>对象)

作者:Nakano_May
原文链接:https://juejin.cn/post/7196680499678740535
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值