// JpaRepositoryFactoryBean创建Repository的getObject就是通过JpaRepositoryFactory.getRepository获取
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;
}
}
// 查询方法执行拦截器,包含命名查询,普通查询,以及按照jpa命名规范都在这里完成的
class QueryExecutorMethodInterceptor {
public QueryExecutorMethodInterceptor(RepositoryInformation repositoryInformation, ProjectionFactory projectionFactory) {
// 结果查询的处理器,使用类型转换器对返回结果进行转换
this.resultHandler = new QueryExecutionResultHandler(CONVERSION_SERVICE);
// 创建一个查询方法的策略
Optional<QueryLookupStrategy> lookupStrategy = getQueryLookupStrategy(queryLookupStrategyKey, RepositoryFactorySupport.this.evaluationContextProvider);
// 如果不存在查找策略,但是存在查询方法,抛出异常
if (!lookupStrategy.isPresent() && repositoryInformation.hasQueryMethods()) {
throw new IllegalStateException("You have defined query method in the repository but");
}
// 使用查找策略查找查询方法,将方法对应映射成RepositoryQuery可执行的query对象
this.queries = lookupStrategy.map(it -> mapMethodsToQuery(repositoryInformation, it, projectionFactory)).orElse(Collections.emptyMap());
}
// 根据标注@EnableJpaRepositories的queryLookupStrategy方法查询方法查找策略
// 根据不同的策略处理目标方法
protected Optional<QueryLookupStrategy> getQueryLookupStrategy(@Nullable Key key, QueryMethodEvaluationContextProvider evaluationContextProvider) {
return Optional.of(JpaQueryLookupStrategy.create(entityManager, key, extractor, evaluationContextProvider, escapeCharacter)
{
// 默认策略为,如果方法不存在,则创建查询
switch (key != null ? key : Key.CREATE_IF_NOT_FOUND) {
// 直接创建查询
case CREATE:
return new CreateQueryLookupStrategy(em, extractor, escape);
// 使用@Query注解创建查询
case USE_DECLARED_QUERY:
return new DeclaredQueryLookupStrategy(em, extractor, evaluationContextProvider);
// 上面两者的兼容版本,先使用@Query注解查找,如果不存在,在使用方法名创建
case CREATE_IF_NOT_FOUND:
return new CreateIfNotFoundQueryLookupStrategy(em, extractor,
new CreateQueryLookupStrategy(em, extractor, escape),
new DeclaredQueryLookupStrategy(em, extractor, evaluationContextProvider));
default:
throw new IllegalArgumentException(String.format("Unsupported query lookup strategy %s!", key));
}
});
}
// 将方法映射成RepositoryQuery对象
private Map<Method, RepositoryQuery> mapMethodsToQuery(RepositoryInformation repositoryInformation, QueryLookupStrategy lookupStrategy, ProjectionFactory projectionFactory) {
/**
* {@link DefaultRepositoryInformation#getQueryMethods()}
*/
// 获取找的的查询方法
return repositoryInformation.getQueryMethods().stream()
// 解析查询方法中的查询注解,参数,查询等信息
// 封装成可执行的Query对象
.map(method -> lookupQuery(method, repositoryInformation, lookupStrategy, projectionFactory)) //
// 执行监听器
.peek(pair -> invokeListeners(pair.getSecond())) //
.collect(Pair.toMap());
}
// 查找查询方法的信息
private Pair<Method, RepositoryQuery> lookupQuery(Method method, RepositoryInformation information, QueryLookupStrategy strategy, ProjectionFactory projectionFactory) {
/**
* {@link JpaQueryLookupStrategy}
*/
// 使用查询策略,解析查询方法,将查询的信息封装为可执行的Query方法
return Pair.of(method, strategy.resolveQuery(method, information, projectionFactory, namedQueries));
}
// 查询查询创建监听器
private void invokeListeners(RepositoryQuery query) {
// 在构造方法中
// QueryCollectingQueryCreationListener collectingListener = new QueryCollectingQueryCreationListener();
// this.queryPostProcessors.add(collectingListener);
class QueryCollectingQueryCreationListener implements QueryCreationListener<RepositoryQuery> {
private final List<QueryMethod> queryMethods = new ArrayList<>();
// 创建的回调方法
public void onCreation(RepositoryQuery query) {
// 保存query中可执行的方法
this.queryMethods.add(query.getQueryMethod());
}
}
// 执行QueryCollectingQueryCreationListener监听器,在创建了方法对应的Query对象之后执行对应回调
for (QueryCreationListener listener : queryPostProcessors) {
// 解析该类的泛型信息,也就是RepositoryQuery
ResolvableType typeArgument = ResolvableType.forClass(QueryCreationListener.class, listener.getClass()).getGeneric(0);
// 如果解析到了泛型类
if (typeArgument != null && typeArgument.isAssignableFrom(ResolvableType.forClass(query.getClass()))) {
// 回调监听器的创建方法
/**
* {@link QueryCollectingQueryCreationListener#onCreation(RepositoryQuery)}
*/
listener.onCreation(query);
}
}
}
// 拦截方法
public Object invoke(@SuppressWarnings("null") MethodInvocation invocation) throws Throwable {
// 获取需要执行的方法
Method method = invocation.getMethod();
// 获取查询执行器的是适配器
QueryExecutionConverters.ExecutionAdapter executionAdapter = QueryExecutionConverters.getExecutionAdapter(method.getReturnType());
// 不存在适配器
if (executionAdapter == null) {
// 执行目标方法
Object res = doInvoke(invocation){
// 获取方法
Method method = invocation.getMethod();
// 如果命名查询中包含此方法
if (hasQueryFor(method){
return queries.containsKey(method);
}) {
// 获取到可执行的Query对象执行目标方法
return queries.get(method).execute(invocation.getArguments());
}
// 放行
return invocation.proceed();
}
// 处理结果,类型转换,给集合默认值等等
return resultHandler.postProcessInvocationResult(res, method);
}
return executionAdapter.apply(() -> resultHandler.postProcessInvocationResult(doInvoke(invocation), method));
}
}
// JPA查询方法的查找策略
public class JpaQueryLookupStrategy {
// 抽象的查询策略
private abstract static class AbstractQueryLookupStrategy implements QueryLookupStrategy {
// 实体管理器
private final EntityManager em;
// 查询提取器,不同的厂商实现提取方式不一样
private final QueryExtractor provider;
public AbstractQueryLookupStrategy(EntityManager em, QueryExtractor extractor) {
this.em = em;
this.provider = extractor;
}
// 解析查询方法
public final RepositoryQuery resolveQuery(Method method, RepositoryMetadata metadata, ProjectionFactory factory, NamedQueries namedQueries) {
// 解析查询方法,将参数封装成JpaQueryMethod
return resolveQuery(new JpaQueryMethod(method, metadata, factory, provider), em, namedQueries);
}
protected abstract RepositoryQuery resolveQuery(JpaQueryMethod method, EntityManager em, NamedQueries namedQueries);
}
// 查找@Query注解的策略
private static class DeclaredQueryLookupStrategy extends AbstractQueryLookupStrategy {
// 负责提供查询方法的上下文信息,以便框架能够正确地解析和执行这些查询方法
private final QueryMethodEvaluationContextProvider evaluationContextProvider;
public DeclaredQueryLookupStrategy(EntityManager em, QueryExtractor extractor, QueryMethodEvaluationContextProvider evaluationContextProvider) {
super(em, extractor);
this.evaluationContextProvider = evaluationContextProvider;
}
// 解析查询语句
protected RepositoryQuery resolveQuery(JpaQueryMethod method, EntityManager em, NamedQueries namedQueries) {
// 解析Query注解,返回可执行的Query类
RepositoryQuery query = JpaQueryFactory.INSTANCE.fromQueryAnnotation(method, em, evaluationContextProvider)
{
// 通过Query中的SQL进行解析
return fromMethodWithQueryString(method, em, method.getAnnotatedQuery() {
// 查询Query注解的value值SQL
return getMergedOrDefaultAnnotationValue(attribute, Query.class, type);
},evaluationContextProvider){
if (queryString == null) {
return null;
}
// 如果是SQL查询,创建一个SQL的执行器
return method.isNativeQuery() ? new NativeJpaQuery(method, em, queryString, evaluationContextProvider, PARSER)
// 否则,使用默认的JPA查询器
: new SimpleJpaQuery(method, em, queryString, evaluationContextProvider, PARSER);
}
}
// 如果存在Query注解,直接返回
if (null != query) {
return query;
}
// 找存储过程@Procedure注解
query = JpaQueryFactory.INSTANCE.fromProcedureAnnotation(method, em) {
// 如果不存在@Procedure注解,直接返回
if (!method.isProcedureQuery()) {
return null;
}
// 返回存储过程的查询类
return new StoredProcedureJpaQuery(method, em);
}
// 如果存在@Procedure注解,直接返回
if (null != query) {
return query;
}
// 其他情况,@Query中不存在SQL语句
String name = method.getNamedQueryName() {
// 先获取Query注解的名称
String annotatedName = getAnnotationValue("name", String.class);
// 没有写name属性,返回类名.方法名
return StringUtils.hasText(annotatedName) ? annotatedName : super.getNamedQueryName() {
return String.format("%s.%s", getDomainClass().getSimpleName(), method.getName());
}
}
// 如果命名查询中已经定义了该方法
if (namedQueries.hasQuery(name)) {
// 获取对应的查询语句
String queryString = namedQueries.getQuery(name);
// 上面有解释,又到了@Query的环节,上面找的是@Query的SQL,现在找的是@Query的name,然后在通过name到命名查询(jpa-named-queries.properties配置文件)中找到对应的SQL
return JpaQueryFactory.INSTANCE.fromMethodWithQueryString(method, em, queryString, evaluationContextProvider);
}
// 如果命名查询中也不存在该方法
query = NamedQuery.lookupFrom(method, em) {
// 获取到查询名称,上面也有解释
// 先获取Query注解的名称
// 没有写name属性,返回类名.方法名
final String queryName = method.getNamedQueryName();
// 是否存在命名查询
if (!hasNamedQuery(em, queryName) {
// 新建一个实体管理器
EntityManager lookupEm = em.getEntityManagerFactory().createEntityManager();
try {
// 尝试用EntityManager创建命名查询,只有在实体类中定义了命名查询才能通过,否则抛出异常
// @NamedQuery(name = "User.findUserByName", query = "select u FROM User u where u.name ='luck'")
// public class User {}
// 提示: 这种存在一种特殊情况,如果命名查询的名称正好符合默认的规则"类名.方法名"
// 那么,没有加@Query和加了@Query但没有设置name的作用是一样的
lookupEm.createNamedQuery(queryName);
return true;
} catch (IllegalArgumentException e) {
// 没有定义该命名查询
return false;
} finally {
// 关闭连接
lookupEm.close();
}
}){
// 返回空,@Query注解的情况处理不了这个方法
return null;
}
// 如果在实体中定义了该命名查询,返回NamedQuery
RepositoryQuery query = new NamedQuery(method, em);
return query;
}
// 如果处理@Query情况成功,直接返回对应的可执行的Query对象
if (null != query) {
return query;
}
// 返回null,表示无法处理Query注解命名查询的逻辑,抛出异常
throw new IllegalStateException(String.format("Did neither find a NamedQuery nor an annotated query for method %s!", method));
}
}
// 根据方法命按照命名规则创建查询
private static class CreateQueryLookupStrategy extends AbstractQueryLookupStrategy {
// 负责提供查询方法的上下文信息,以便框架能够正确地解析和执行这些查询方法
private final PersistenceProvider persistenceProvider;
// 转义字符处理器
private final EscapeCharacter escape;
public CreateQueryLookupStrategy(EntityManager em, QueryExtractor extractor, EscapeCharacter escape) {
super(em, extractor);
this.persistenceProvider = PersistenceProvider.fromEntityManager(em);
this.escape = escape;
}
// 创建一个Query对象,也就是按照SpringDataJpa的命名规则,解析方法名为树,提取字段和关键字
protected RepositoryQuery resolveQuery(JpaQueryMethod method, EntityManager em, NamedQueries namedQueries) {
return new PartTreeJpaQuery(method, em, persistenceProvider, escape) {
}
}
}
// 上面两种的兼容版本
private static class CreateIfNotFoundQueryLookupStrategy extends AbstractQueryLookupStrategy {
// 处理@Query注解的策略
private final DeclaredQueryLookupStrategy lookupStrategy;
// 直接创建名称树查询的策略
private final CreateQueryLookupStrategy createStrategy;
public CreateIfNotFoundQueryLookupStrategy(EntityManager em, QueryExtractor extractor, CreateQueryLookupStrategy createStrategy, DeclaredQueryLookupStrategy lookupStrategy) {
super(em, extractor);
this.createStrategy = createStrategy;
this.lookupStrategy = lookupStrategy;
}
// 解析查询
protected RepositoryQuery resolveQuery(JpaQueryMethod method, EntityManager em, NamedQueries namedQueries) {
// 先处理@Query,如果处理不成功则创建
try {
return lookupStrategy.resolveQuery(method, em, namedQueries);
} catch (IllegalStateException e) {
return createStrategy.resolveQuery(method, em, namedQueries);
}
}
}
}
// JPA命名规范解析树查询
class PartTreeJpaQuery {
PartTreeJpaQuery(JpaQueryMethod method, EntityManager em, PersistenceProvider persistenceProvider, EscapeCharacter escape) {
super(method, em);
this.em = em;
this.escape = escape;
// 实体类型
Class<?> domainClass = method.getEntityInformation().getJavaType();
// 方法参数
this.parameters = method.getParameters();
// 可能是用于检查查询方法是否包含动态投影
// 动态投影是指在查询中根据条件动态选择要返回的字段或属性
// 或者特殊的参数分页或者排序
boolean recreationRequired = parameters.hasDynamicProjection() || parameters.potentiallySortsDynamically();
try {
// 构建一个方法树
this.tree = new PartTree(method.getName(), domainClass) {
+
String KEYWORD_TEMPLATE = "(%s)(?=(\\p{Lu}|\\P{InBASIC_LATIN}))";
+
String QUERY_PATTERN = "find|read|get|query|stream";
+
String COUNT_PATTERN = "count";
+
String EXISTS_PATTERN = "exists";
+
String DELETE_PATTERN = "delete|remove";
+
Pattern PREFIX_TEMPLATE = Pattern.compile("^(" + QUERY_PATTERN + "|" + COUNT_PATTERN + "|" + EXISTS_PATTERN + "|" + DELETE_PATTERN + ")((\\p{Lu}.*?))??By");
// 主题,就是需要执行的最终操作,是查询,删除...操作
private final Subject subject;
// 运算到主题中的条件
private final Predicate predicate;
// 匹配上面的关键字
Matcher matcher = PREFIX_TEMPLATE.matcher(source);
// 如果方法名没有匹配到
if(!matcher.find())
{
// 指定空主题
this.subject = new Subject(Optional.empty());
// 方法名作为条件
this.predicate = new Predicate(source, domainClass);
}
// 方法名匹配到了关键字
else
{
// 使用匹配到的第一处关键字作为主题
this.subject = new Subject(Optional.of(matcher.group(0))) {
// 主题为去查
this.distinct =subject.map(it ->it.contains(DISTINCT)).
orElse(false);
// 主题为查询数量
this.count =
matches(subject, COUNT_BY_TEMPLATE);
// 是否存在
this.exists =
matches(subject, EXISTS_BY_TEMPLATE);
// 删除
this.delete =
matches(subject, DELETE_BY_TEMPLATE);
// 分页结果
this.maxResults =
returnMaxResultsIfFirstKSubjectOrNull(subject);
}
// 截取条件
this.predicate = new Predicate(source.substring(matcher.group().length()), domainClass) {
// 截取排序字段条件和普通字段
// 例如: AgeAndNameOrderByAgeDesc -> AgeAndName AgeDesc
String[] parts = split(detectAndSetAllIgnoreCase(predicate), ORDER_BY);
// 先通过OR条件进行切割,再将两边的条件使用And进行连接,最终返回这些字段的节点树
this.nodes =Arrays.stream(
split(parts[0], "Or"))
.
filter(StringUtils::hasText)
// 再将两边的条件使用And进行连接
.
map(part ->new
OrPart(part, domainClass, alwaysIgnoreCase) {
String[] split = split(source, "And");
// 保存And的字段
this.children = Arrays.stream(split)
.filter(StringUtils::hasText)
.map(part -> new Part(part, domainClass, alwaysIgnoreCase))//
.collect(Collectors.toList());
})
.
collect(Collectors.toList());
}
}
}
// 参数个数和解析到的字段条件进行校验
validate(tree, parameters, method.toString());
// 创建一个count查询,主要是处理分页
this.countQuery = new CountQueryPreparer(persistenceProvider, recreationRequired);
// 如果没有进行分页处理,创建一个QueryPreparer
// 内部是创建一个CriteriaQuery查询,并设置查询参数
this.query = tree.isCountProjection() ? countQuery : new QueryPreparer(persistenceProvider, recreationRequired);
} catch (Exception o_O) {
throw new IllegalArgumentException(String.format("Failed to create query for method %s! %s", method, o_O.getMessage()), o_O);
}
}
}
// 命名查询器
class PropertiesBasedNamedQueries implements NamedQueries {
// 对应这命名查询的配置文件属性
// 它是作为一个Bean传入的,是通过PropertiesFactoryBean生成的Bean
// User.findAllAdultUsers = SELECT u FROM User u WHERE u.id > 1
private final @NonNull
Properties properties;
// 命名查询配置文件jpa-named-queries.properties中是否存在该方法
// User.findAllAdultUsers=SELECT u FROM User u WHERE u.id > 1
public boolean hasQuery(String queryName) {
return properties.containsKey(queryName);
}
// 查找命名查询的sql
// User.findAllAdultUsers=SELECT u FROM User u WHERE u.id > 1
public String getQuery(String queryName) {
// 获取到命名查询的sql
String query = properties.getProperty(queryName);
// 如果没有找到对应的命名查询,抛出异常
if (query == null) {
throw new IllegalArgumentException(String.format(NO_QUERY_FOUND, queryName));
}
// 返回命名查询对应的sql
return query;
}
}
// 创建Properties的Bean实例
class PropertiesFactoryBean extends PropertiesLoaderSupport implements FactoryBean<Properties> {
// 需要加载的资源文件路径
private Resource[] locations;
// 本身存在的本地变量数据
protected Properties[] localProperties;
// Properties单实例
private Properties singletonInstance;
if(this.singleton)
{
// 所以这个配置就是FactoryBean本身存在的属性变量,与当前需要加载的路径对应的配置进行合并的属性
this.singletonInstance = createProperties();
}
// 创建Properties对象
protected Properties createProperties() throws IOException {
return mergeProperties();
}
// 合并原有的Properties属性
protected Properties mergeProperties() throws IOException {
Properties result = new Properties();
// 是否允许覆盖本地的配置,默认为false,就是一个执行时机的问题
// 如果允许覆盖,那么需要先加载当前配置文件,在进行本地合并覆盖
// 如果不允许覆盖,那么先保存所有的本地变量,然后在记载最新的属性
if (this.localOverride) {
// 加载属性
loadProperties(result);
}
// 如果存在本地配置信息,进行覆盖
if (this.localProperties != null) {
// 遍历所有的本地配置
for (Properties localProp : this.localProperties) {
// 将加载的配置与本地的配置进行合并,重复的进行覆盖
CollectionUtils.mergePropertiesIntoMap(localProp, result);
}
}
// 是否覆盖本地的配置,默认为false
if (!this.localOverride) {
loadProperties(result);
}
return result;
}
// 加载属性
protected void loadProperties(Properties props) throws IOException {
// 是否设置需要加载的属性文件路径
if (this.locations != null) {
// 如果存在
for (Resource location : this.locations) {
// 加载属性到props中
PropertiesLoaderUtils.fillProperties(props, new EncodedResource(location, this.fileEncoding), this.propertiesPersister)
{
// 获取流数据
InputStream stream = location.getInputStream();
// 加载对Properties中
props.load(reader);
}
}
}
}
}
SpringDataJpa中,直接按照命名规范命名就能查询的实现原理
于 2024-04-01 19:33:23 首次发布