jpa初始化与查询过程

关于jpa初始化

实体类扫描

 @EntityScan(basePackages = {
 })

来到 EntityScanPackages.Registrar.class

扫描并注册beandefinition

 public static void register(BeanDefinitionRegistry registry, Collection<String> packageNames) {
     if (registry.containsBeanDefinition(BEAN)) {//被提前注册直接添加构造函数即可
       BeanDefinition beanDefinition = registry.getBeanDefinition(BEAN);
       ConstructorArgumentValues constructorArguments = beanDefinition.getConstructorArgumentValues();
       constructorArguments.addIndexedArgumentValue(0, addPackageNames(constructorArguments, packageNames));
     }
     else {
       GenericBeanDefinition beanDefinition = new GenericBeanDefinition();//创建beandefinition
       beanDefinition.setBeanClass(EntityScanPackages.class);//配置bean class
       beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue(0,
           StringUtils.toStringArray(packageNames)); //将package添加为构造函数
       beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
       registry.registerBeanDefinition(BEAN, beanDefinition);
     }
   }

来到构造函数也就是bean初始化的过程

   EntityScanPackages(String... packageNames) {
     List<String> packages = new ArrayList<>();
     for (String name : packageNames) {
       if (StringUtils.hasText(name)) {
         packages.add(name);
       }
     }
     this.packageNames = Collections.unmodifiableList(packages);//返回一个不可被修改的list
   }

bean被注册完后来到jpa自动配置类 这里默认是有hibernate实现

 HibernateJpaConfiguration
  //数据源 jpa参数  bean工厂 jta事务管理 hibernate参数 数据库连接池信息提供者 hibernate参数改造器等
 HibernateJpaConfiguration(DataSource dataSource, JpaProperties jpaProperties,
       ConfigurableListableBeanFactory beanFactory, ObjectProvider<JtaTransactionManager> jtaTransactionManager,
       HibernateProperties hibernateProperties,
       ObjectProvider<Collection<DataSourcePoolMetadataProvider>> metadataProviders,
       ObjectProvider<SchemaManagementProvider> providers,
       ObjectProvider<PhysicalNamingStrategy> physicalNamingStrategy,
       ObjectProvider<ImplicitNamingStrategy> implicitNamingStrategy,
 ​
   }

创建jpa供应商适配器

JpaVendorAdapter 一个spi接口 这里是hibernate提供

 PersistenceProvider getPersistenceProvider()//获取持久化提供者
  default String getPersistenceProviderRootPackage() {//提供者根路径 这里是org.hibernate
     return null;
   }
 getJpaPropertyMap //获取jpa参数
 getEntityManagerFactoryInterface() //获取实体管理工厂接口 class类型
 @Bean
   @ConditionalOnMissingBean
   public JpaVendorAdapter jpaVendorAdapter() {
     AbstractJpaVendorAdapter adapter = createJpaVendorAdapter();//new HibernateJpaVendorAdapter();hibernate提供
   //....
     return adapter;
   }

创建实体工厂构建器

   @Bean
   @ConditionalOnMissingBean
   public EntityManagerFactoryBuilder entityManagerFactoryBuilder(JpaVendorAdapter jpaVendorAdapter,
       ObjectProvider<PersistenceUnitManager> persistenceUnitManager,
       ObjectProvider<EntityManagerFactoryBuilderCustomizer> customizers) {
     EntityManagerFactoryBuilder builder = new EntityManagerFactoryBuilder(jpaVendorAdapter,
         this.properties.getProperties(), persistenceUnitManager.getIfAvailable());
     customizers.orderedStream().forEach((customizer) -> customizer.customize(builder));
     return builder;
   }

通过构造器创建EntityManagerFactoryBean 实现了FactoryBean接口最终会创建出EntityManagerFactory

   public LocalContainerEntityManagerFactoryBean entityManagerFactory(EntityManagerFactoryBuilder factoryBuilder) {
     //获取供应商属性
     Map<String, Object> vendorProperties = getVendorProperties();
     customizeVendorProperties(vendorProperties);
     return //配置数据源 实体扫描包  属性 
       factoryBuilder.dataSource(this.dataSource).packages(getPackagesToScan()).properties(vendorProperties)
         .mappingResources(getMappingResources()).jta(isJta()).build();
   }

直接看build方法

 public LocalContainerEntityManagerFactoryBean build() {
     //创建出factoryBean先
       LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
     //配置jpa厂家适配器
       entityManagerFactoryBean.setJpaVendorAdapter(EntityManagerFactoryBuilder.this.jpaVendorAdapter);
 ​
   //是否开启jta事务
       if (this.jta) {
         entityManagerFactoryBean.setJtaDataSource(this.dataSource);
       }
       else {
         //配置数据源
         entityManagerFactoryBean.setDataSource(this.dataSource);
       }
   //配置需要扫描的类
       entityManagerFactoryBean.setPackagesToScan(this.packagesToScan);
       entityManagerFactoryBean.getJpaPropertyMap().putAll(EntityManagerFactoryBuilder.this.jpaProperties);
     
 ​
   }

初始化 LocalContainerEntityManagerFactoryBean 调用初始化方法 afterPropertiesSet 初始化持久化单元管理 调用链如下

 afterPropertiesSet     
 DefaultPersistenceUnitManager preparePersistenceUnitInfos //获取项目classurl通过classLoader获取 配置DataSource 
 readPersistenceUnitInfos //读取相关配置 实体类等 
 buildDefaultPersistenceUnitInfo //构建持久化单元信息 或有的实体类信息等
   scanPackage                     //扫描配置类 获取到managedClassNames 所有的实体类
 获取持久化提供者 这里是hibernate
  super.afterPropertiesSet 
     buildNativeEntityManagerFactory
         createNativeEntityManagerFactory//创建连接等
 创建EntityManagerFactory 启动数据连接池 连接数据库
 为EntityManagerFactory创建代理 用事务和Query类型参数查询 DefaultPersistenceUnitManager用于持久化

@ EnableJpaRepositories 代理查询方法

来到RepositoryBeanDefinitionRegistrarSupport

 RepositoryConfigurationDelegate delegate = new RepositoryConfigurationDelegate(configurationSource, resourceLoader,
         environment);
 ​
 delegate.registerRepositoriesIn(registry, extension);
 ​
 //首先获取所有的配置类
 Collection<RepositoryConfiguration<RepositoryConfigurationSource>> configurations = extension
         .getRepositoryConfigurations(configurationSource, resourceLoader, inMultiStoreMode);
 //通过获取的配置创建beanDefinition  使用 JpaRepositoryFactoryBean实现
 BeanDefinitionBuilder definitionBuilder = builder.build(configuration);
 //添加属性 事务管理 实体管理
 extension.postProcess(definitionBuilder, configurationSource);
 //通过类名构建beanName
 String beanName = configurationSource.generateBeanName(beanDefinition);
 //注册beanDefinition
 registry.registerBeanDefinition(beanName, beanDefinition);

//获取所有的repositoryCOnfiguration

 

   public <T extends RepositoryConfigurationSource> Collection<RepositoryConfiguration<T>> getRepositoryConfigurations(
       T configSource, ResourceLoader loader, boolean strictMatchesOnly) {
 ​
     Set<RepositoryConfiguration<T>> result = new HashSet<>();
 ​
     for (BeanDefinition candidate : configSource.getCandidates(loader)) {
 ​
       RepositoryConfiguration<T> configuration = getRepositoryConfiguration(candidate, configSource);
       Class<?> repositoryInterface = loadRepositoryInterface(configuration,
           getConfigurationInspectionClassLoader(loader));//获取到interface
 ​
     return result;
   }

getCandidates方法用户获取所有被jpa配置的类

 RepositoryComponentProvider scanner = new RepositoryComponentProvider(getIncludeFilters(), registry);
 //这里通过RepositoryComponent扫描所有匹配的类使用filter的方式 构造方法截取如下
     //
       super.addIncludeFilter(new InterfaceTypeFilter(Repository.class));
       super.addIncludeFilter(new AnnotationTypeFilter(RepositoryDefinition.class, true, true));
   //同时派出NoRepositoryBean注解
     addExcludeFilter(new AnnotationTypeFilter(NoRepositoryBean.class));
 ​
 //所以只需要实现接口即可,不需要标注@Repository注解
 ​
     scanner.setConsiderNestedRepositoryInterfaces(shouldConsiderNestedRepositories());
     scanner.setEnvironment(environment);
     scanner.setResourceLoader(loader);
 ​
     getExcludeFilters().forEach(it -> scanner.addExcludeFilter(it));
   //通过findCandidateComponents获取所有的beanDefinition
     return Streamable.of(() -> getBasePackages().stream()//
         .flatMap(it -> scanner.findCandidateComponents(it).stream()));

### jpa查询

jpa查询底层使用的动态代理生成,由hibernate实现

jap 查询代理

首先通过接口被spring的JdkDynamicAopProxy代理

代理对象为SimpleJpaRepository 可以看到当前SimpleJpaRepository被jdk动态代理了,内部实现了一些单表的crud操作

image-20210806100509855

从spring缓存中获取advised 创建MethodInvocation 这里就是springaop的开始了

 MethodInvocation invocation =
             new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
         // Proceed to the joinpoint through the interceptor chain.
         retVal = invocation.proceed();

ReflectiveMethodInvocation#proceed()

 SimpleJpaRepositoryif (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {//当前拦截的index是否为左后一个执行完了 那就直接通过SimpleJpaRepository执行方法,它们都实现了JpaRepository
       return invokeJoinpoint(); 
 }
 //获取拦截的advice 当前拦截器Index加一
 Object interceptorOrInterceptionAdvice =
         this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
 //这里是特殊的Advice需要匹配 直接跳过
 if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
   ...
 }
 else {
       // It's an interceptor, so we just invoke it: The pointcut will have
       // been evaluated statically before this object was constructed.
       return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
 }

第一个拦截器 ExposeInvocationInterceptor

   public Object invoke(MethodInvocation mi) throws Throwable {
     MethodInvocation oldInvocation = invocation.get();
     invocation.set(mi);//保存当前的上下文以便后面的拦截器使用  ReflectiveMethodInvocation
     try {
       return mi.proceed(); //继续调用下一层
     }
     finally {
       invocation.set(oldInvocation);
     }
   }

第二个拦截器 CrudMethodMetadataPostProcessor

 对curd方法元数据进行处理
   Method method = invocation.getMethod();
 ​
       if (!implementations.contains(method)) {//是否为接口自带实现方法
         return invocation.proceed();
       }

第三个拦截器 PersistenceExceptionTranslationInterceptor

 持久层异常处理

第四个 TransactionInterceptor

 事务拦截器 用于对事务的处理
 获取事务管理器与事务属性 判断是否开启事务处理

第5个拦截器 DefaultMethodInvokingMethodInterceptor

 对默认方法进行处理
 if (!method.isDefault()) {
       return invocation.proceed();
     }

第6个拦截器 QueryExecutorMethodInterceptor

 查询执行器方法
 Method method = invocation.getMethod();
 ​
 QueryExecutionConverters.ExecutionAdapter executionAdapter = QueryExecutionConverters //比如list 根据返回类型获取对应的执行器
         .getExecutionAdapter(method.getReturnType());
 if (executionAdapter == null) {
       return resultHandler.postProcessInvocationResult(doInvoke(invocation), method);//对结果进行处理
 }

doInvok方法

 private Object doInvoke(MethodInvocation invocation) throws Throwable {
     Method method = invocation.getMethod();
     if (hasQueryFor(method)) {//是否为查询方法
       QueryMethodInvoker invocationMetadata = invocationMetadataCache.get(method);
       if (invocationMetadata == null) {
         invocationMetadata = new QueryMethodInvoker(method);//创建方法执行器
         invocationMetadataCache.put(method, invocationMetadata);
       }
       RepositoryQuery repositoryQuery = queries.get(method);
       return invocationMetadata.invoke(repositoryQuery, invocation.getArguments());
     }
     return invocation.proceed();
   }

获取执行器执行方法 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值