Spring Data JPA系列
1、SpringBoot集成JPA及基本使用
2、Spring Data JPA Criteria查询、部分字段查询
3、Spring Data JPA数据批量插入、批量更新真的用对了吗
4、Spring Data JPA的一对一、LazyInitializationException异常、一对多、多对多操作
5、Spring Data JPA自定义Id生成策略、复合主键配置、Auditing使用
6、【源码】Spring Data JPA原理解析之Repository的自动注入(一)
7、【源码】Spring Data JPA原理解析之Repository的自动注入(二)
8、【源码】Spring Data JPA原理解析之Repository执行过程及SimpleJpaRepository源码
9、【源码】Spring Data JPA原理解析之Repository自定义方法命名规则执行原理(一)
10、【源码】Spring Data JPA原理解析之Repository自定义方法命名规则执行原理(二)
11、【源码】Spring Data JPA原理解析之Repository自定义方法添加@Query注解的执行原理
12、【源码】SpringBoot事务注册原理
13、【源码】Spring Data JPA原理解析之事务注册原理
前言
JPA是Java Persistence API的简称,中文名Java持久层API。JPA采用ORM对象关系映射,以Java面向对象的编程思想,在javax.persistence包下提供对实体对象的CRUD操作,将开发者从繁琐的JDBC和SQL代码中解脱出来。
在数据库的操作中,为了处理脏读、不可重复读、幻读等问题,需要通过事务来处理。本篇从源码的角度和大家一下分享一下Spring Data JPA中的Repository的事务注册原理。
Repository的事务注册
在Spring框架中,数据操作的事务是通过添加@Transaction注解来实现的。详见:
【源码】SpringBoot事务注册原理-CSDN博客
在Spring Data JPA中,实现事务也是只需要在对应的方法中添加@Transaction注解即可。下面从源码的角度来分析一下事务实现的原理。
【源码】Spring Data JPA原理解析之Repository的自动注入(二)-CSDN博客
在上面的博文中分享了Repository bean的创建。Respository的bean是一个通过ProxyFactory创建的动态代理对象。源码如下:
public abstract class RepositoryFactorySupport implements BeanClassLoaderAware, BeanFactoryAware {
/**
* 返回给定接口的存储库实例,该实例由为自定义逻辑提供实现逻辑的实例支持。
*/
@SuppressWarnings({ "unchecked" })
public <T> T getRepository(Class<T> repositoryInterface, RepositoryFragments fragments) {
if (logger.isDebugEnabled()) {
logger.debug(LogMessage.format("Initializing repository instance for %s…", repositoryInterface.getName()));
}
Assert.notNull(repositoryInterface, "Repository interface must not be null");
Assert.notNull(fragments, "RepositoryFragments must not be null");
ApplicationStartup applicationStartup = getStartup();
StartupStep repositoryInit = onEvent(applicationStartup, "spring.data.repository.init", repositoryInterface);
repositoryBaseClass.ifPresent(it -> repositoryInit.tag("baseClass", it.getName()));
StartupStep repositoryMetadataStep = onEvent(applicationStartup, "spring.data.repository.metadata",
repositoryInterface);
// 获取repository元数据,包括Repository<T, ID>中的T类型、ID类型、接口类型(如GoodsRepository)等
RepositoryMetadata metadata = getRepositoryMetadata(repositoryInterface);
repositoryMetadataStep.end();
StartupStep repositoryCompositionStep = onEvent(applicationStartup, "spring.data.repository.composition",
repositoryInterface);
repositoryCompositionStep.tag("fragment.count", String.valueOf(fragments.size()));
// 获取
RepositoryComposition composition = getRepositoryComposition(metadata, fragments);
// 获取Repository信息,getRepositoryInformation()返回一个RepositoryInformation对象。
// 如子类JpaRepositoryFactory,指定baseClass为SimpleJpaRepository.class
RepositoryInformation information = getRepositoryInformation(metadata, composition);
repositoryCompositionStep.tag("fragments", () -> {
StringBuilder fragmentsTag = new StringBuilder();
for (RepositoryFragment<?> fragment : composition.getFragments()) {
if (fragmentsTag.length() > 0) {
fragmentsTag.append(";");
}
fragmentsTag.append(fragment.getSignatureContributor().getName());
fragmentsTag.append(fragment.getImplementation().map(it -> ":" + it.getClass().getName()).orElse(""));
}
return fragmentsTag.toString();
});
repositoryCompositionStep.end();
StartupStep repositoryTargetStep = onEvent(applicationStartup, "spring.data.repository.target",
repositoryInterface);
// 获取目标Repository对象,SimpleJpaRepository对象
Object target = getTargetRepository(information);
repositoryTargetStep.tag("target", target.getClass().getName());
repositoryTargetStep.end();
RepositoryComposition compositionToUse = composition.append(RepositoryFragment.implemented(target));
validate(information, compositionToUse);
// Create proxy
// 创建代理对象
StartupStep repositoryProxyStep = onEvent(applicationStartup, "spring.data.repository.proxy", repositoryInterface);
ProxyFactory result = new ProxyFactory();
result.setTarget(target);
// 代理对象实现的接口
result.setInterfaces(repositoryInterface, Repository.class, TransactionalProxy.class);
if (MethodInvocationValidator.supports(repositoryInterface)) {
result.addAdvice(new MethodInvocationValidator());
}
// 添加界面
result.addAdvisor(ExposeInvocationInterceptor.ADVISOR);
if (!postProcessors.isEmpty()) {
StartupStep repositoryPostprocessorsStep = onEvent(applicationStartup, "spring.data.repository.postprocessors",
repositoryInterface);
// 执行后置处理
// CrudMethodMetadataPostProcessor
// TransactionalRepositoryProxyPostProcessor
// JpaRepositoryFactory构造方法中加入的内部处理器,
// 添加SurroundingTransactionDetectorMethodInterceptor,记录是否处理状态
// PersistenceExceptionTranslationRepositoryProxyPostProcessor
// EventPublishingRepositoryProxyPostProcessor
postProcessors.forEach(processor -> {
StartupStep singlePostProcessor = onEvent(applicationStartup, "spring.data.repository.postprocessor",
repositoryInterface);
singlePostProcessor.tag("type", processor.getClass().getName());
processor.postProcess(result, information);
singlePostProcessor.end();
});
repositoryPostprocessorsStep.end();
}
if (DefaultMethodInvokingMethodInterceptor.hasDefaultMethods(repositoryInterface)) {
// 添加DefaultMethodInvokingMethodInterceptor拦截器
result.addAdvice(new DefaultMethodInvokingMethodInterceptor());
}
Optional<QueryLookupStrategy> queryLookupStrategy = getQueryLookupStrategy(queryLookupStrategyKey,
evaluationContextProvider);
// 添加QueryExecutorMethodInterceptor拦截器
result.addAdvice(new QueryExecutorMethodInterceptor(information, getProjectionFactory(), queryLookupStrategy,
namedQueries, queryPostProcessors, methodInvocationListeners));
// 添加ImplementationMethodExecutionInterceptor拦截器
result.addAdvice(
new ImplementationMethodExecutionInterceptor(information, compositionToUse, methodInvocationListeners));
T repository = (T) result.getProxy(classLoader);
repositoryProxyStep.end();
repositoryInit.end();
if (logger.isDebugEnabled()) {
logger
.debug(LogMessage.format("Finished creation of repository instance for %s.",
repositoryInterface.getName()));
}
return repository;
}
}
在生成代理对象之前,如果有后置处理器postProcessors,则执行后置处理器的postProcess()方法。在后置处理器中,有一个TransactionalRepositoryProxyPostProcessor。
JpaRepositoryFactoryBean
【源码】Spring Data JPA原理解析之Repository的自动注入(一)-CSDN博客
在上面的博文中分享了JpaRepositoriesAutoConfiguration的源码,在Spring Data JPA自动注入时,会自动注入JpaRepositoryConfigExtension,在JpaRepositoryConfigExtension中getRepositoryFactoryBeanClassName()方法,返回JpaRepositoryFactoryBean.class.getName(),该类最终会被装载到Spring IOC容器中。
JpaRepositoryFactoryBean初始化时,执行父父类RepositoryFactoryBeanSupport的afterPropertiesSet()方法,在该方法中,主要执行如下:
3.1)调用抽象方法createRepositoryFactory()创建Repository工厂对象,在TransactionalRepositoryFactoryBeanSupport中实现了该方法;
在createRepositoryFactory()方法中,创建了Repository工厂之后,添加了两个后置处理器,其中一个为TransactionalRepositoryProxyPostProcessor。
3.2)为3.1)中的Repository工厂对象设置查询查找策略、NamedQueries、后置处理器等;
3.3)调用3.1)中的Repository工厂对象,调用getRepository()创建代理的Repository对象;
详细可以看【源码】Spring Data JPA原理解析之Repository的自动注入(二)
TransactionalRepositoryFactoryBeanSupport
TransactionalRepositoryFactoryBeanSupport的源码如下:
package org.springframework.data.repository.core.support;
public abstract class TransactionalRepositoryFactoryBeanSupport<T extends Repository<S, ID>, S, ID>
extends RepositoryFactoryBeanSupport<T, S, ID> implements BeanFactoryAware {
private String transactionManagerName = TxUtils.DEFAULT_TRANSACTION_MANAGER;
private @Nullable RepositoryProxyPostProcessor txPostProcessor;
private @Nullable RepositoryProxyPostProcessor exceptionPostProcessor;
private boolean enableDefaultTransactions = true;
// 忽略其他
@Override
protected final RepositoryFactorySupport createRepositoryFactory() {
// 调用抽象方法,创建一个RepositoryFactorySupport对象,JpaRepositoryFactory对象
RepositoryFactorySupport factory = doCreateRepositoryFactory();
// 添加两个后置处理器,分别为PersistenceExceptionTranslationRepositoryProxyPostProcessor
// 和TransactionalRepositoryProxyPostProcessor。在setBeanFactory()方法中初始化
RepositoryProxyPostProcessor exceptionPostProcessor = this.exceptionPostProcessor;
if (exceptionPostProcessor != null) {
factory.addRepositoryProxyPostProcessor(exceptionPostProcessor);
}
RepositoryProxyPostProcessor txPostProcessor = this.txPostProcessor;
if (txPostProcessor != null) {
factory.addRepositoryProxyPostProcessor(txPostProcessor);
}
return factory;
}
protected abstract RepositoryFactorySupport doCreateRepositoryFactory();
public void setBeanFactory(BeanFactory beanFactory) {
Assert.isInstanceOf(ListableBeanFactory.class, beanFactory);
super.setBeanFactory(beanFactory);
// 创建后置处理器
ListableBeanFactory listableBeanFactory = (ListableBeanFactory) beanFactory;
this.txPostProcessor = new TransactionalRepositoryProxyPostProcessor(listableBeanFactory, transactionManagerName,
enableDefaultTransactions);
this.exceptionPostProcessor = new PersistenceExceptionTranslationRepositoryProxyPostProcessor(listableBeanFactory);
}
}
1)TransactionalRepositoryFactoryBeanSupport实现了BeanFactoryAware,在初始化前,会执行setBeanFactory()方法,在该方法中,创建了两个后置处理器,分别为PersistenceExceptionTranslationRepositoryProxyPostProcessor和TransactionalRepositoryProxyPostProcessor;
2)在createRepositoryFactory()方法中,执行子类JpaRepositoryFactoryBean的doCreateRepositoryFactory()方法,创建JpaRepositoryFactory对象。并添加了1)中创建的两个后置处理器,其中一个为TransactionalRepositoryProxyPostProcessor;
TransactionalRepositoryProxyPostProcessor
在TransactionalRepositoryProxyPostProcessor处理器中,会向代理工厂添加TransactionInterceptor拦截器。
TransactionalRepositoryProxyPostProcessor的代码如下:
package org.springframework.data.repository.core.support;
class TransactionalRepositoryProxyPostProcessor implements RepositoryProxyPostProcessor {
private final BeanFactory beanFactory;
private final String transactionManagerName;
private final boolean enableDefaultTransactions;
public TransactionalRepositoryProxyPostProcessor(ListableBeanFactory beanFactory, String transactionManagerName,
boolean enableDefaultTransaction) {
Assert.notNull(beanFactory, "BeanFactory must not be null");
Assert.notNull(transactionManagerName, "TransactionManagerName must not be null");
this.beanFactory = beanFactory;
this.transactionManagerName = transactionManagerName;
this.enableDefaultTransactions = enableDefaultTransaction;
}
public void postProcess(ProxyFactory factory, RepositoryInformation repositoryInformation) {
// 定义一个TransactionInterceptor对象
TransactionInterceptor transactionInterceptor = new TransactionInterceptor();
// 设置RepositoryAnnotationTransactionAttributeSource
transactionInterceptor.setTransactionAttributeSource(
new RepositoryAnnotationTransactionAttributeSource(repositoryInformation, enableDefaultTransactions));
transactionInterceptor.setTransactionManagerBeanName(transactionManagerName);
transactionInterceptor.setBeanFactory(beanFactory);
transactionInterceptor.afterPropertiesSet();
// 添加TransactionInterceptor拦截器
factory.addAdvice(transactionInterceptor);
}
static class RepositoryAnnotationTransactionAttributeSource extends AnnotationTransactionAttributeSource {
private static final long serialVersionUID = 7229616838812819438L;
private final RepositoryInformation repositoryInformation;
private final boolean enableDefaultTransactions;
public RepositoryAnnotationTransactionAttributeSource(RepositoryInformation repositoryInformation,
boolean enableDefaultTransactions) {
// 执行父类AnnotationTransactionAttributeSource,事务的分析器
// 为JtaTransactionAnnotationParser和SpringTransactionAnnotationParser。
// 即支持javax.transaction.Transactional的@Transactional注解和spring的@Transactional
super(true);
Assert.notNull(repositoryInformation, "RepositoryInformation must not be null");
// enableDefaultTransactions默认为true
this.enableDefaultTransactions = enableDefaultTransactions;
// DefaultRepositoryInformation对象
this.repositoryInformation = repositoryInformation;
}
@Override
@Nullable
protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
// Don't allow no-public methods as required.
if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
return null;
}
// Ignore CGLIB subclasses - introspect the actual user class.
Class<?> userClass = targetClass == null ? targetClass : ProxyUtils.getUserClass(targetClass);
// The method may be on an interface, but we need attributes from the target class.
// If the target class is null, the method will be unchanged.
Method specificMethod = ClassUtils.getMostSpecificMethod(method, userClass);
// If we are dealing with method with generic parameters, find the original method.
// 如果正在处理具有泛型参数的方法,请找到原始方法。
specificMethod = BridgeMethodResolver.findBridgedMethod(specificMethod);
TransactionAttribute txAtt = null;
if (specificMethod != method) {
// Fallback is to look at the original method.
txAtt = findTransactionAttribute(method);
if (txAtt != null) {
return txAtt;
}
// Last fallback is the class of the original method.
txAtt = findTransactionAttribute(method.getDeclaringClass());
if (txAtt != null || !enableDefaultTransactions) {
return txAtt;
}
}
// First try is the method in the target class.
txAtt = findTransactionAttribute(specificMethod);
if (txAtt != null) {
return txAtt;
}
// Second try is the transaction attribute on the target class.
txAtt = findTransactionAttribute(specificMethod.getDeclaringClass());
if (txAtt != null) {
return txAtt;
}
if (!enableDefaultTransactions) {
return null;
}
// Fallback to implementation class transaction settings of nothing found
// return findTransactionAttribute(method);
Method targetClassMethod = repositoryInformation.getTargetClassMethod(method);
if (targetClassMethod.equals(method)) {
return null;
}
txAtt = findTransactionAttribute(targetClassMethod);
if (txAtt != null) {
return txAtt;
}
txAtt = findTransactionAttribute(targetClassMethod.getDeclaringClass());
if (txAtt != null) {
return txAtt;
}
return null;
}
}
}
5.1 在postProcess()方法中,执行如下:
1)声明一个TransactionInterceptor对象;
2)声明一个RepositoryAnnotationTransactionAttributeSource对象;
3)添加transactionManagerName和beanFactory;
4)在ProxyFactory添加TransactionInterceptor拦截器;
5.2 RepositoryAnnotationTransactionAttributeSource注解事务属性资源类为内部类,该类继承AnnotationTransactionAttributeSource。RepositoryAnnotationTransactionAttributeSource的构造方法中,执行父类的构造方法。
在AnnotationTransactionAttributeSource的构造方法中,会添加注解事务的解析器。添加了SpringTransactionAnnotationParser和JtaTransactionAnnotationParser。分别用于解析org.springframework.transaction.annotation包和javax.transaction包下的@Transactional注解。即在代码中使用两个包的@Transactional注解都可以实现事务。
在RepositoryAnnotationTransactionAttributeSource的computeTransactionAttribute()方法中,会调用父类AnnotationTransactionAttributeSource的findTransactionAttribute(),进而执行determineTransactionAttribute()方法,遍历解析器,解析对应的@Transactional注解。
结尾
限于篇幅,本篇先分享到这里。
关于本篇内容你有什么自己的想法或独到见解,欢迎在评论区一起交流探讨下吧。