SpringBoot具体整合rabbitMQ可参考:SpringBoot2.0应用(四):SpringBoot2.0之spring-data-jpa

JpaRepositories自动注入

当项目中存在org.springframework.data.jpa.repository.JpaRepository类,并且已经注入过数据源javax.sql.DataSource,同时没有注入过org.springframework.data.jpa.repository.config.JpaRepositoryConfigExtensionorg.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean时,会通过@Import注解导入org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfigureRegistrar,由它完成对JPA的支持。JpaRepositoriesAutoConfigureRegistrar又继承自AbstractRepositoryConfigurationSourceSupport。来看下AbstractRepositoryConfigurationSourceSupport的具体内容。

public abstract class AbstractRepositoryConfigurationSourceSupport
implements BeanFactoryAware, ImportBeanDefinitionRegistrar, ResourceLoaderAware,
EnvironmentAware { private ResourceLoader resourceLoader; private BeanFactory beanFactory; private Environment environment; @Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
BeanDefinitionRegistry registry) {
new RepositoryConfigurationDelegate(getConfigurationSource(registry),
this.resourceLoader, this.environment).registerRepositoriesIn(registry,
getRepositoryConfigurationExtension());
} ......
}

可以看出,到AbstractRepositoryConfigurationSourceSupportRepository的Bean进行了定义。下面来具体看看Repositoryd的创建。

Repository的创建

我们先来看下RepositoryConfigurationDelegateregisterRepositoriesIn方法。

	public List<BeanComponentDefinition> registerRepositoriesIn(BeanDefinitionRegistry registry,
RepositoryConfigurationExtension extension) { extension.registerBeansForRoot(registry, configurationSource); RepositoryBeanDefinitionBuilder builder = new RepositoryBeanDefinitionBuilder(registry, extension, resourceLoader,
environment);
List<BeanComponentDefinition> definitions = new ArrayList<>(); for (RepositoryConfiguration<? extends RepositoryConfigurationSource> configuration : extension
.getRepositoryConfigurations(configurationSource, resourceLoader, inMultiStoreMode)) { BeanDefinitionBuilder definitionBuilder = builder.build(configuration); extension.postProcess(definitionBuilder, configurationSource); if (isXml) {
extension.postProcess(definitionBuilder, (XmlRepositoryConfigurationSource) configurationSource);
} else {
extension.postProcess(definitionBuilder, (AnnotationRepositoryConfigurationSource) configurationSource);
} AbstractBeanDefinition beanDefinition = definitionBuilder.getBeanDefinition();
String beanName = configurationSource.generateBeanName(beanDefinition);
......
beanDefinition.setAttribute(FACTORY_BEAN_OBJECT_TYPE, configuration.getRepositoryInterface()); registry.registerBeanDefinition(beanName, beanDefinition);
definitions.add(new BeanComponentDefinition(beanDefinition, beanName));
} return definitions;
}

到这里其实只是创建了repository的实体Bean的BeanDefinition。前期准备做好了,实际创建repository是在RepositoryFactorySupport的getRepository方法。

	public <T> T getRepository(Class<T> repositoryInterface, RepositoryFragments fragments) {
Assert.notNull(repositoryInterface, "Repository interface must not be null!");
Assert.notNull(fragments, "RepositoryFragments must not be null!"); RepositoryMetadata metadata = getRepositoryMetadata(repositoryInterface);
RepositoryComposition composition = getRepositoryComposition(metadata, fragments);
RepositoryInformation information = getRepositoryInformation(metadata, composition); validate(information, composition); Object target = getTargetRepository(information); // Create proxy
ProxyFactory result = new ProxyFactory();
result.setTarget(target);
result.setInterfaces(repositoryInterface, Repository.class, TransactionalProxy.class); if (MethodInvocationValidator.supports(repositoryInterface)) {
result.addAdvice(new MethodInvocationValidator());
} result.addAdvice(SurroundingTransactionDetectorMethodInterceptor.INSTANCE);
result.addAdvisor(ExposeInvocationInterceptor.ADVISOR); postProcessors.forEach(processor -> processor.postProcess(result, information)); 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)); return (T) result.getProxy(classLoader);
}

首先去获取我们写的repository接口的元数据,包括实体的ID类型,管理的实体类型等。接着获取repository的组合,主要包含repository的方法信息。然后再根据它俩的组合得到一个target。这个target其实就是一个SimpleJpaRepository实体,里面包含了一些通用的方法。只有这些还不够,于是有了后面的代理工厂,对这个target进行进一步处理。包括事务支持,异常处理和SQL创造等。我们主要看一下SQL创建。创建的方法在DeclaredQueryLookupStrategyresolveQuery中。

protected RepositoryQuery resolveQuery(JpaQueryMethod method, EntityManager em, NamedQueries namedQueries) {

			RepositoryQuery query = JpaQueryFactory.INSTANCE.fromQueryAnnotation(method, em, evaluationContextProvider);

			if (null != query) {
return query;
} query = JpaQueryFactory.INSTANCE.fromProcedureAnnotation(method, em); if (null != query) {
return query;
} String name = method.getNamedQueryName();
if (namedQueries.hasQuery(name)) {
return JpaQueryFactory.INSTANCE.fromMethodWithQueryString(method, em, namedQueries.getQuery(name),
evaluationContextProvider);
} query = NamedQuery.lookupFrom(method, em); if (null != query) {
return query;
} throw new IllegalStateException(
String.format("Did neither find a NamedQuery nor an annotated query for method %s!", method));
}

该方法的逻辑是先找有注解的,这个包括@Query@Procedure,接着是根据关键字创建,然后是通用方法。


本篇到此结束,如果读完觉得有收获的话,欢迎点赞、关注、加公众号【贰级天災】,查阅更多精彩历史!!!

SpringBoot2.0源码分析(四):spring-data-jpa分析的更多相关文章

  1. SpringBoot2.0源码分析(一):SpringBoot简单分析

    SpringBoot2.0简单介绍:SpringBoot2.0应用(一):SpringBoot2.0简单介绍 本系列将从源码角度谈谈SpringBoot2.0. 先来看一个简单的例子 @SpringB ...

  2. SpringBoot2.0源码分析(三):整合RabbitMQ分析

    SpringBoot具体整合rabbitMQ可参考:SpringBoot2.0应用(三):SpringBoot2.0整合RabbitMQ RabbitMQ自动注入 当项目中存在org.springfr ...

  3. SpringBoot2.0源码分析(二):整合ActiveMQ分析

    SpringBoot具体整合ActiveMQ可参考:SpringBoot2.0应用(二):SpringBoot2.0整合ActiveMQ ActiveMQ自动注入 当项目中存在javax.jms.Me ...

  4. AFNetworking2.0源码解析<四>

    结构 AFURLResponseSerialization负责解析网络返回数据,检查数据是否合法,把NSData数据转成相应的对象,内置的转换器有json,xml,plist,image,用户可以很方 ...

  5. [Android FrameWork 6.0源码学习] ViewGroup的addView函数分析

    Android中整个的View的组装是采用组合模式. ViewGroup就相当与树根,各种Layout就相当于枝干,各种子View,就相当于树叶. 至于View类.我们就当它是个种子吧.哈哈! Vie ...

  6. AFNetworking (3.1.0) 源码解析 <四>

    这次主要看一下文件夹Security中的类AFSecurityPolicy----安全策略类. AFSecurityPolicy主要的作用是验证HTTPS请求证书的有效性,在iOS9之后,默认不能发送 ...

  7. Spring Boot从入门到精通(九)整合Spring Data JPA应用框架

    JPA是什么? JPA全称Java Persistence API,是Sun官方提出的Java持久化规范.是JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中. ...

  8. spring boot 2.0 源码分析(四)

    在上一章的源码分析里,我们知道了spring boot 2.0中的环境是如何区分普通环境和web环境的,以及如何准备运行时环境和应用上下文的,今天我们继续分析一下run函数接下来又做了那些事情.先把r ...

  9. Solr4.8.0源码分析(23)之SolrCloud的Recovery策略(四)

    Solr4.8.0源码分析(23)之SolrCloud的Recovery策略(四) 题记:本来计划的SolrCloud的Recovery策略的文章是3篇的,但是没想到Recovery的内容蛮多的,前面 ...

随机推荐

  1. Maven之pom.xml配置文件详解

    此文非原创,摘自:https://www.baidu.com/link?url=GlGgW21nijIiULDZj0RfPH8ofqGMqEnAzXiym7O3hfrZM5nFH2enukemBNTX ...

  2. apt-get update 问题

    W: 仓库 “cdrom://Ubuntu 16.04.1 LTS _Xenial Xerus_ - Release amd64 (20160719) xenial Release” 没有 Relea ...

  3. hbase常用操纵操作——增删改查

    查询某个资金账户的信息 get 'dmp:hbase_tags','资金账号' 创建表 create 'emp', 'personal data', 'professional data' 在HBas ...

  4. php学习备注笔记

    一: PHP内核相关 http://blog.csdn.net/ywh147/article/details/40188411 [深入PHP内核(二)——SAPI探究] http://www.nowa ...

  5. Android逆向破解表单注册程序

    Android逆向破解表单注册程序 Android开发 ADT: android studio(as) 程序界面如下,注册码为6位随机数字,注册成功时弹出通知注册成功,注册失败时弹出通知注册失败. 布 ...

  6. dell T130服务器加内存

    需求:客户一台dell T130塔式服务器,由于本机只有一条8G内存,系统运行比较慢,需要再增加一条8G内存. 增加过程:第一次增加时由于没有注意机器上内存频率是2133的,所以新增加的一条2400频 ...

  7. XML学习总结一

    1.声明 <?xml version="1.0"  encoding="gb2312"?> version属性指定该文档遵守的版本号,通常为1.0X ...

  8. Openvswtich 学习笔记

    场景: 创建一个Virtual Switch,支持VLAN,支持MAC-Learning 包含下面四个Port: P1, truck port P2, VLAN 20 P3, P4 VLAN 30 包 ...

  9. 背水一战 Windows 10 (107) - 通知(Toast): 提示音, 特定场景

    [源码下载] 背水一战 Windows 10 (107) - 通知(Toast): 提示音, 特定场景 作者:webabcd 介绍背水一战 Windows 10 之 通知(Toast) 提示音 特定场 ...

  10. git常用命令速查:创建,修改提交,撤销,切换分支,合并分支,变基解决冲突

    创建 $ git init  #在当前目录下创建一个空的本地仓库 $ rm -rf  .git  #删除本地仓库 $ git add .  #把当前目录下的所有文件添加到暂存区 $ git commi ...