SpringDataJpa的Repository接口是如何创建实现类的原理

// 创建Repository接口的Bean
class JpaRepositoryFactoryBean extends TransactionalRepositoryFactoryBeanSupport extends RepositoryFactoryBeanSupport implements FactoryBean {
    // 构造方法,需要传递一个Repository接口
    public JpaRepositoryFactoryBean(Class<? extends T> repositoryInterface) {
        super(repositoryInterface);
    }

    // 给当前Repository设置EntityManager
    @PersistenceContext
    public void setEntityManager(EntityManager entityManager) {
        this.entityManager = entityManager;
    }

    public void setBeanFactory(BeanFactory beanFactory) {
        // 初始化事务后置处理器
        this.txPostProcessor = new TransactionalRepositoryProxyPostProcessor(listableBeanFactory, transactionManagerName, enableDefaultTransactions);
        // 初始化异常后置处理器
        this.exceptionPostProcessor = new PersistenceExceptionTranslationRepositoryProxyPostProcessor(listableBeanFactory) {
            // 添加一个异常处理拦截器
            factory.addAdvice(new PersistenceExceptionTranslationInterceptor());
        }
    }

    public void afterPropertiesSet() {
        Assert.state(entityManager != null, "EntityManager must not be null!");
        // 创建Repository的Bean的工厂类,因为实际上JpaRepositoryFactoryBean的getObject生成的Bean是从JpaRepositoryFactory工厂中获取的Bean
        this.factory = createRepositoryFactory() {
            // 创建Repository的Bean的工厂
            RepositoryFactorySupport factory = doCreateRepositoryFactory() {
                return createRepositoryFactory(entityManager) {
                    // 实际生产Repository接口实现类Bean的工厂
                    JpaRepositoryFactory jpaRepositoryFactory = new JpaRepositoryFactory(entityManager);
                    // 给工厂设置实体路径解析器
                    jpaRepositoryFactory.setEntityPathResolver(entityPathResolver);
                    // 设置转义字符
                    jpaRepositoryFactory.setEscapeCharacter(escapeCharacter);
                    // 返回Repository工厂
                    return jpaRepositoryFactory;
                }
            }
            // 设置异常后置处理器
            RepositoryProxyPostProcessor exceptionPostProcessor = this.exceptionPostProcessor;
            if (exceptionPostProcessor != null) {
                factory.addRepositoryProxyPostProcessor(exceptionPostProcessor);
            }
            // 设置事务后置处理器
            /**
             * {@link TransactionalRepositoryProxyPostProcessor(ListableBeanFactory, String, boolean)}
             */
            RepositoryProxyPostProcessor txPostProcessor = this.txPostProcessor;
            if (txPostProcessor != null) {
                factory.addRepositoryProxyPostProcessor(txPostProcessor);
            }
            return factory;
        }
        // 设置查找策略,这些参数都是在BeanDefinition的时机就设置进来了
        this.factory.setQueryLookupStrategyKey(queryLookupStrategyKey);
        // 设置命名查询器
        this.factory.setNamedQueries(namedQueries);
        // 设置计算上下文的提供者,其实就是找Spring中EvaluationContextExtension的Bean,在初始化期间,就注册了JpaEvaluationContextExtension,用于解析SPEL
        this.factory.setEvaluationContextProvider(evaluationContextProvider.orElseGet(() -> QueryMethodEvaluationContextProvider.DEFAULT));
        this.factory.setBeanClassLoader(classLoader);
        this.factory.setBeanFactory(beanFactory);
        // 事件发布者
        if (publisher != null) {
            // 添加一个事件发布的后置处理器,用于处理实体的被触发之后的事件
            // 用于在Repository操作实体之后,会发布的事件,处理实体中@DomainEvents方法和@AfterDomainEventPublication的方法
            this.factory.addRepositoryProxyPostProcessor(new EventPublishingRepositoryProxyPostProcessor(publisher));
        }
        // 设置所有Repository的基类,在@EnableJpaRepositories(repositoryBaseClass = LuckRepository.class)设置,到时候Repository实现类就是LuckRepository
        repositoryBaseClass.ifPresent(this.factory::setRepositoryBaseClass);

        // 将Repository接口的自定义实现类转换转换为一个RepositoryFragments碎片
        RepositoryFragments customImplementationFragment = customImplementation
                .map(RepositoryFragments::just)
                .orElseGet(RepositoryFragments::empty);
        // 将所有存在的Repository碎片接口与自定义实现进行合并成一个大的碎片接口组合
        // 这样,RepositoryFragments就组合了所有实现类的功能
        RepositoryFragments repositoryFragmentsToUse = this.repositoryFragments
                .orElseGet(RepositoryFragments::empty)
                .append(customImplementationFragment);
        // 获取Repository接口的元数据信息
        this.repositoryMetadata = this.factory.getRepositoryMetadata(repositoryInterface);
        // 缓存实体的信息并返回
        // MappingContext是用来映射实体与数据库之间关系的机制,getPersistentEntity就是在缓存实体的信息
        this.mappingContext.ifPresent(it -> it.getPersistentEntity(repositoryMetadata.getDomainType()));
        // 生成Repository接口的实现类,传递的是一个函数式接口,只有到需要用到才会回调
        /**
         * {@link JpaRepositoryFactory#getRepository(Class, RepositoryFragments)}
         */
        this.repository = Lazy.of(() -> this.factory.getRepository(repositoryInterface, repositoryFragmentsToUse));
        // 如果不是懒加载
        if (!lazyInit) {
            // 执行this.factory.getRepository回调,生成repository实现类
            this.repository.get();
        }
    }

    public T getObject() {
        return this.repository.get();
    }
}

// 实际生产Repository接口实现类Bean的工厂
class JpaRepositoryFactory {
    // 创建代理的后置处理器,就是给要给代理添加拦截器
    private final List<RepositoryProxyPostProcessor> postProcessors;
    // Repository的基类
    private Optional<Class<?>> repositoryBaseClass;
    // 命名查询器
    private NamedQueries namedQueries = new PropertiesBasedNamedQueries(new Properties());

    public JpaRepositoryFactory(EntityManager entityManager) {
        // 实体管理器
        this.entityManager = entityManager;
        // 查询的提取器的提供商,不同提供商的提取方式不一样,,可能是Hibernate persistence provider,EclipseLink persistence provider,Use standard JPA
        this.extractor = PersistenceProvider.fromEntityManager(entityManager);
        // crud方法的元数据后置处理器
        this.crudMethodMetadataPostProcessor = new CrudMethodMetadataPostProcessor();
        // 实体路径解析器
        this.entityPathResolver = SimpleEntityPathResolver.INSTANCE;
        // 添加RepositoryProxy代理的后置处理器
        addRepositoryProxyPostProcessor(crudMethodMetadataPostProcessor);
        // 添加RepositoryProxy代理的后置处理器
        addRepositoryProxyPostProcessor((factory, repositoryInformation) -> {
            // 如果有Repository中的方法,返回Stream,则需要添加一个代理方法拦截器
            // SurroundingTransactionDetectorMethodInterceptor,它是一个枚举
            if (hasMethodReturningStream(repositoryInformation.getRepositoryInterface())) {
                SurroundingTransactionDetectorMethodInterceptor advice = SurroundingTransactionDetectorMethodInterceptor.INSTANCE
                {
                    private final ThreadLocal<Boolean> SURROUNDING_TX_ACTIVE = new ThreadLocal<>();
                    // 保存当前线程是否真实获取到事务信息标记
                    SURROUNDING_TX_ACTIVE.set(TransactionSynchronizationManager.isActualTransactionActive());
                    // 放行
                    Object res = invocation.proceed();
                    // 删除标记
                    SURROUNDING_TX_ACTIVE.remove();
                    return res;
                }
                // 添加拦截器
                factory.addAdvice(advice);
            }
        });
        // 如果持久化机制的提供商是EclipseLink
        if (extractor.equals(PersistenceProvider.ECLIPSELINK)) {
            // 添加查询创建监听器
            addQueryCreationListener(new EclipseLinkProjectionQueryCreationListener(entityManager));
        }
    }

    // 获取Repository的实现
    public <T> T getRepository(Class<T> repositoryInterface, RepositoryFragments fragments) {
        // 获取Repository接口的元数据信息
        RepositoryMetadata metadata = getRepositoryMetadata(repositoryInterface);
        // 将所有碎片接口进行组合,返回一个Repository组合类
        RepositoryComposition composition = getRepositoryComposition(metadata, fragments);
        // 获取Repository接口信息
        RepositoryInformation information = getRepositoryInformation(metadata, composition);
        // 校验接口是否存在实现类
        validate(information, composition);
        // 生成Repository实现类
        Object target = getTargetRepository(information);
        // 准备给Repository创建代理对象
        ProxyFactory result = new ProxyFactory();
        // 设置目标类
        result.setTarget(target);
        // 设置需要实现的接口
        result.setInterfaces(repositoryInterface, Repository.class, TransactionalProxy.class);
        // 如果支持拦截该接口,添加一个拦截器
        if (MethodInvocationValidator.supports(repositoryInterface)) {
            result.addAdvice(new MethodInvocationValidator());
        }
        // 添加一个切面它只负责保存当前正在执行的MethodInvocation对象
        result.addAdvisor(ExposeInvocationInterceptor.ADVISOR);
        // 执行所有的后置处理器
        /**
         * {@link TransactionalRepositoryProxyPostProcessor#postProcess(ProxyFactory, RepositoryInformation)}
         * {@link JpaRepositoryFactory(EntityManager entityManager)}
         */
        postProcessors.forEach(processor -> processor.postProcess(result, information));
        // 该接口是否存在默认方法,如果存在,需要添加拦截器
        if (DefaultMethodInvokingMethodInterceptor.hasDefaultMethods(repositoryInterface)) {
            // 添加默认方法拦截器
            result.addAdvice(new DefaultMethodInvokingMethodInterceptor());
        }
        // 创建映射信息
        ProjectionFactory projectionFactory = getProjectionFactory(classLoader, beanFactory);
        // 添加查询方法执行拦截器,包含命名查询,普通查询等等
        result.addAdvice(new QueryExecutorMethodInterceptor(information, projectionFactory));
        // 将当前接口自动生成的实现类也进行组合
        composition = composition.append(RepositoryFragment.implemented(target));
        // 添加实现类方法执行器的拦截器
        result.addAdvice(new ImplementationMethodExecutionInterceptor(composition));
        // 获取Repository接口实现类的代理对象
        T repository = (T) result.getProxy(classLoader);
        // 返回代理对象
        return repository;
    }

    // 生成Repository实现类
    protected final JpaRepositoryImplementation<?, ?> getTargetRepository(RepositoryInformation information) {
        // 获取Repository实现类
        JpaRepositoryImplementation<?, ?> repository = getTargetRepository(information, entityManager) {
            // 获取实体信息
            JpaEntityInformation<?, Serializable> entityInformation = getEntityInformation(information.getDomainType());
            // 创建实现类对象
            Object repository = getTargetRepositoryViaReflection(information, entityInformation, entityManager) {
                // 获取Repository的基类
                Class<?> baseClass = information.getRepositoryBaseClass();
                // 获取实现类对象
                return getTargetRepositoryViaReflection(baseClass, constructorArguments);
            }
            // 生成的实现类必须是JpaRepositoryImplementation类型
            Assert.isInstanceOf(JpaRepositoryImplementation.class, repository);
            // 返回生成的实现类
            return (JpaRepositoryImplementation<?, ?>) repository;
        }
        // 给实现类设置CRUD的元数据信息,就是生成一个CrudMethodMetadata的元数据对象
        repository.setRepositoryMethodMetadata(crudMethodMetadataPostProcessor.getCrudMethodMetadata());
        // 设置转义字符
        repository.setEscapeCharacter(escapeCharacter);
        // 返回实现类
        return repository;
    }

    // 获取Repository接口信息
    private RepositoryInformation getRepositoryInformation(RepositoryMetadata metadata, RepositoryComposition composition) {
        // 生成缓存Key
        RepositoryInformationCacheKey cacheKey = new RepositoryInformationCacheKey(metadata, composition);
        // 缓存Repository的信息
        return repositoryInformationCache.computeIfAbsent(cacheKey, key -> {
            // 获取Repository接口的实现类基类
            Class<?> baseClass = repositoryBaseClass.orElse(getRepositoryBaseClass(metadata));
            // 返回默认的接口实现
            return new DefaultRepositoryInformation(metadata, baseClass, composition);
        });
    }

    // 将所有碎片接口进行组合,返回一个Repository组合类
    private RepositoryComposition getRepositoryComposition(RepositoryMetadata metadata, RepositoryFragments fragments) {
        RepositoryComposition composition = getRepositoryComposition(metadata) {
            // 创建一个空组合
            RepositoryComposition composition = RepositoryComposition.empty();
            // 是响应式的Repository
            if (metadata.isReactiveRepository()) {
                return composition.withMethodLookup(MethodLookups.forReactiveTypes(metadata)).withArgumentConverter(REACTIVE_ARGS_CONVERTER);
            }
            // 创建Repository类型的方法查找器
            MethodLookup lookup = MethodLookups.forRepositoryTypes(metadata) {
                MethodPredicate direct = direct() {
                    // 获取一个匹配器,将可执行的方法与给定的候选方法比较,参数个数,参数类型,方法名称进行对比
                    MethodPredicate direct = (invoked, candidate) -> candidate.getName().equals(invoked.getName())
                            && candidate.getParameterCount() == invoked.getParameterCount()
                            && Arrays.equals(candidate.getParameterTypes(), invoked.getParameterTypes());
                    // 返回一个Lookup
                    return () -> Collections.singletonList(direct);
                }
                // 将该查找器与给定查找器的匹配器进行合并
                return direct.and(new RepositoryAwareMethodLookup(repositoryMetadata) {
                }) {
                    // getLookups:List<MethodPredicate>,获取所有的匹配器
                    // 返回一个新的Lookup
                    return () -> Stream.concat(getLookups().stream(), other.getLookups().stream()).collect(Collectors.toList());
                }
            }
            // 根据方法查找器,已经原有的碎片接口实现类集合创建一个新的组合
            return composition.withMethodLookup(lookup) {
                return new RepositoryComposition(fragments, methodLookup, argumentConverter);
            }
        }
        // 获取queryDsl碎片接口实现集合
        RepositoryFragments repositoryAspects = getRepositoryFragments(metadata);
        // 将原有的碎片接口实现类集合与queryDsl碎片接口实现进行组合
        return composition.append(fragments).append(repositoryAspects);
    }

    // 获取queryDsl碎片接口实现集合
    protected RepositoryComposition.RepositoryFragments getRepositoryFragments(RepositoryMetadata metadata) {
        // 创建空的碎片集合
        RepositoryComposition.RepositoryFragments fragments = RepositoryComposition.RepositoryFragments.empty();
        // 是否存在dslRepository查询
        boolean isQueryDslRepository = QUERY_DSL_PRESENT && QuerydslPredicateExecutor.class.isAssignableFrom(metadata.getRepositoryInterface());
        // 如果存在dsl查询
        if (isQueryDslRepository) {
            // dsl与响应式不兼容
            if (metadata.isReactiveRepository()) {
                throw new InvalidDataAccessApiUsageException("Cannot combine Querydsl and reactive repository support in a single interface");
            }
            // 获取jpa的实体信息
            JpaEntityInformation<?, Serializable> entityInformation = getEntityInformation(metadata.getDomainType());
            // 获取CRUD方法的元数据信息
            CrudMethodMetadata crudMethodMetadata = crudMethodMetadataPostProcessor.getCrudMethodMetadata() {
                // 获取一个CrudMethodMetadata代理对象
                ProxyFactory factory = new ProxyFactory();
                factory.addInterface(CrudMethodMetadata.class);
                // 在crudMethodMetadataPostProcessor中,会添加一个拦截器,CrudMethodMetadataPopulatingMethodInterceptor
                // 会将当前MethodInvocation保存
                factory.setTargetSource(new ThreadBoundTargetSource());
                return (CrudMethodMetadata) factory.getProxy(this.classLoader);
            }
            // 获取queryDsl的接口碎片实现
            Object querydslFragment = getTargetRepositoryViaReflection(QuerydslJpaPredicateExecutor.class, entityInformation, entityManager, entityPathResolver, crudMethodMetadata);
            // 拼接dsl碎片接口实现
            fragments = fragments.append(RepositoryFragment.implemented(querydslFragment));
        }
        // 返回接口碎片实现集合
        return fragments;
    }

    // 获取queryDsl的接口碎片实现
    protected final <R> R getTargetRepositoryViaReflection(Class<?> baseClass, Object... constructorArguments) {
        // 查找基类QuerydslJpaPredicateExecutor的构造方法
        Optional<Constructor<?>> constructor = ReflectionUtils.findConstructor(baseClass, constructorArguments);
        // 实例化QuerydslJpaPredicateExecutor实现类
        return constructor.map(it -> (R) BeanUtils.instantiateClass(it, constructorArguments))
                .orElseThrow(() -> new IllegalStateException(String.format("No suitable constructor found on %s to match the given arguments: %s. Make sure you implement a constructor taking these", baseClass, Arrays.stream(constructorArguments).map(Object::getClass).collect(Collectors.toList()))));
    }

    // 获取JPA实体信息
    public <T, ID> JpaEntityInformation<T, ID> getEntityInformation(Class<T> domainClass) {
        return (JpaEntityInformation<T, ID>) JpaEntityInformationSupport.getEntityInformation(domainClass, entityManager)
        {
            // 它提供对持久化单元中实体元模型的访问
            Metamodel metamodel = entityManager.getMetamodel();
            // 如果实体类是Persistable类型,返回JpaPersistableEntityInformation实体信息
            if (Persistable.class.isAssignableFrom(domainClass)) {
                return new JpaPersistableEntityInformation(domainClass, metamodel);
            }
            // 否则返回Jpa元模型实体信息
            return new JpaMetamodelEntityInformation(domainClass, metamodel);
        }
    }

    // 校验接口的自定义方法是否给定了实现
    private void validate(RepositoryInformation repositoryInformation, RepositoryComposition composition) {
        /**
         * {@link DefaultRepositoryInformation#hasCustomMethod()}
         */
        // 如果存在自定义的方法
        if (repositoryInformation.hasCustomMethod()) {
            // 但是没有找的对应自定义方法的实现,抛出异常
            // 碎片接口对应的实现类为空,也就是没有实现类
            if (composition.isEmpty()) {
                throw new IllegalArgumentException(String.format("You have custom methods in %s but not provided a custom implementation!", repositoryInformation.getRepositoryInterface()));
            }
            // 存在是实现类,校验实现类
            composition.validateImplementation();
        }
        // 空实现,校验Repository接口信息
        validate(repositoryInformation);
    }

}

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
您好,感谢您的提问。创建一个 Spring Data JPARepository 接口非常简单,只需要按照以下步骤操作即可: 1. 创建一个继承自 `JpaRepository` 的接口,指定实体和主键型: ``` public interface UserRepository extends JpaRepository<User, Long> { } ``` 其中,`User` 是您的实体,`Long` 是实体的主键型。`JpaRepository` 是 Spring Data JPA 提供的一个基础 Repository 接口,提供了一些基本的数据操作方法,如插入、删除、更新、查询等。 2. 在您的实体上添加注解,指定表名和主键: ``` @Entity @Table(name = "user") public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String username; private String password; // 省略 getter 和 setter 方法 } ``` 在上述代码中,`@Entity` 注解表示该是一个 JPA 实体,`@Table(name = "user")` 指定该实体对应的数据库表名为 `user`,`@Id` 和 `@GeneratedValue` 注解指定实体的主键。 3. 在您的 Spring Boot 应用程序中,使用 `@EnableJpaRepositories` 注解启用 Spring Data JPA,并指定 Repository 接口的包路径: ``` @SpringBootApplication @EnableJpaRepositories(basePackages = "com.example.repository") public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } } ``` 在上述代码中,`@EnableJpaRepositories` 注解用于启用 Spring Data JPA,`basePackages` 属性指定 Repository 接口的包路径。 4. 在您的服务层或控制器中注入 Repository 接口,即可使用 Spring Data JPA 提供的基本数据操作方法: ``` @RestController public class UserController { @Autowired private UserRepository userRepository; @GetMapping("/users") public List<User> getAllUsers() { return userRepository.findAll(); } } ``` 在上述代码中,`@Autowired` 注解用于自动注入 `UserRepository` 对象,然后在 `getAllUsers` 方法中调用 `findAll` 方法获取所有用户信息。 通过上述步骤创建一个 Spring Data JPARepository 接口非常简单,希望能够帮助到您。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值