在SpringBoot中,我们只要定义好Entity,配置好DataSource,最后实现JpaRepository接口就可以对数据进行CRUD操作。
@Repository
public interface UserDao extends JpaRepository<User, Integer>{
}
是不是很神奇,我们定义了接口,但却没有实现具体的方法,为啥就可以直接对数据源进行了操作呢?今天我们就来看下JpaRepository的实现原理。以下SpringBoot相关源码都是2.1.4版本。
JpaRepositoriesAutoConfiguration
在之前一篇博客Spring Boot JPA–DataSource中,就说明过@EnableAutoConfiguration注解会自动装载spring.factories文件中配置类,其中就包括JpaRepositoriesAutoConfiguration。
可以看到JpaRepositoriesAutoConfiguration引入的条件,是存在DataSource以及JpaRepository。同时导入了JpaRepositoriesAutoConfigureRegistrar,我们来看下这个类做了些什么。
JpaRepositoriesAutoConfigureRegistrar
我们先来看下它的继承关系
我们重点关注下ImportBeanDefinitionRegistrar接口,Spring利用这个接口动态注册Bean,可以理解为实现了类似@Service,@Component等注解的功能。
既然是动态注册Bean,那么注册了哪些Bean呢?我们来看下方法registerBeanDefinitions的实现
方法的逻辑很简单,new了一个RepositoryConfigurationDelegate对象,并且调用了其中registerRepositoriesIn的方法。
我们再来看下getConfigurationSource方法,它生成了AnnotationRepositoryConfigurationSource对象。它保存了构建repository所需的相关配置,包括basePackages,即repository所在包路径
我们再看下getConfiguration以及getAnnotation方法,JpaRepositoriesAutoConfigureRegistrar覆写了这两个方法
结合AnnotationRepositoryConfigurationSource的实现,可知它通过解析@EnableJpaRepositories注解来获取构建repository所需的配置。
在了解注册逻辑之前,我们先来看下@EnableJpaRepositories包含了哪些配置。毕竟在做一道菜之前,我们首先需要了解做菜所需的材料。
EnableJpaRepositories
attribute | type | default | explain |
---|---|---|---|
value | String[] | {} | 同basePackages |
basePackages | String[] | {} | repository所在包路径 |
basePackageClasses | Class<?>[] | {} | repository所包含的class |
includeFilters | Filter[] | {} | 过滤需要处理的repository |
excludeFilters | Filter[] | {} | 过滤不需要处理的repository |
repositoryFactoryBeanClass | Class<?> | JpaRepositoryFactoryBean.class | 生成repository的工厂类 |
repositoryBaseClass | Class<?> | DefaultRepositoryBaseClass.class | repository的实现类 |
entityManagerFactoryRef | String | entityManagerFactory | 生成entityManager的工厂类 |
transactionManagerRef | String | transactionManager | 生成transactionManager的工厂类 |
bootstrapMode | BootstrapMode | BootstrapMode.DEFAULT | repository加载模式,默认在初始化时就进行加载 |
RepositoryConfigurationDelegate
了解了repository注册所需的配置,我们再来看下具体的注册逻辑。
RepositoryConfigurationDelegate是一个委托对象,由它来实现真正的注册流程,具体逻辑在方法registerRepositoriesIn中
我们看下关键逻辑的代码
- 获取所有的RepositoryConfiguration
- postProcess构建beanDefinition
- registerBeanDefinition 注册beanDefinition
可以看到1,2两步都在extension中处理,这里的extension就是JpaRepositoryConfigExtension
JpaRepositoryConfigExtension
我们来看下postProcess方法
JpaRepositoryFactoryBean
JpaRepositoryFactory
SimpleJpaRepository
总结
- JpaRepositoriesAutoConfiguration导入(import) JpaRepositoriesAutoConfigureRegistrar
- JpaRepositoriesAutoConfigureRegistrar.registerBeanDefinitions()
- RepositoryConfigurationDelegate.registerRepositoriesIn()
- JpaRepositoryConfigExtension.postProcess()
- JpaRepositoryFactoryBean.createRepositoryFactory()
- JpaRepositoryFactory.getRepository()