jpa repository工厂类JpaRepositoryFactory

875 阅读3分钟

获取repository实例

JpaRepositoryFactory.getRepository源码

	/**
	 * 返回给定接口的repository实例,该实例由提供自定义逻辑的实现逻辑的实例支持
	 */
	@SuppressWarnings({ "unchecked" })
	public <T> T getRepository(Class<T> repositoryInterface, Object customImplementation) {
		// repository元数据,包括:id类型、实体类型、repository接口类型等
		RepositoryMetadata metadata = getRepositoryMetadata(repositoryInterface);
		// 自定义的实现类class
		Class<?> customImplementationClass = null == customImplementation ? null : customImplementation.getClass();
		// 附加repository特定信息,包括:用于创建代理支持实例的基类、是否自定义方法、repository接口中定义的所有方法等
		// 创建代理实例基类的方法:JpaRepositoryFactory#getRepositoryBaseClass返回SimpleJpaRepository或QueryDslJpaRepository
		RepositoryInformation information = getRepositoryInformation(metadata, customImplementationClass);
		// 校验参数是否合法。提供了一个子类的扩展点
		validate(information, customImplementation);
		// 基类对应的对象实例。例如:SimpleJpaRepository对象实例
		Object target = getTargetRepository(information);

		// 创建代理
		ProxyFactory result = new ProxyFactory();
		result.setTarget(target);
		result.setInterfaces(new Class[] { repositoryInterface, Repository.class });
		// 检测方法是否被事务包围的MethodInterceptor
		result.addAdvice(SurroundingTransactionDetectorMethodInterceptor.INSTANCE);
		// ExposeInvocationInterceptor的一个单例的切面
		result.addAdvisor(ExposeInvocationInterceptor.ADVISOR);
		
		if (TRANSACTION_PROXY_TYPE != null) {
			// 添加TransactionalProxy代理接口
			result.addInterface(TRANSACTION_PROXY_TYPE);
		}
        
		// 执行postProcessor
		for (RepositoryProxyPostProcessor processor : postProcessors) {
			// 包括TransactionalRepositoryFactoryBeanSupport#createRepositoryFactory加入的两个processor:PersistenceExceptionTranslationRepositoryProxyPostProcessor和TransactionalRepositoryProxyPostProcessor
			// RepositoryFactoryBeanSupport#afterPropertiesSet可能加入的EventPublishingRepositoryProxyPostProcessor
			// new JpaRepositoryFactory时加入的CrudMethodMetadataPostProcessor
			processor.postProcess(result, information);
		}

		if (IS_JAVA_8) {
			// 方法拦截器,用于调用repository代理上的默认方法。
			result.addAdvice(new DefaultMethodInvokingMethodInterceptor());
		}
		// 实际底层是:CollectionAwareProjectionFactory。
		ProjectionFactory projectionFactory = getProjectionFactory(classLoader, beanFactory);
		// 自定义方法的拦截器。会为Repository接口中每个查询定义方法Method去构造相应的RepositoryQuery。通过RepositoryQuery#execute执行实际操作
		result.addAdvice(new QueryExecutorMethodInterceptor(information, customImplementation, target, projectionFactory));
		
		return (T) result.getProxy(classLoader);
	}

自定义方法的拦截器

QueryExecutorMethodInterceptor源码

	/**
	 * 此拦截对自定义实现方法的调用,并将其委托给它(如果已配置)。 此外,它解决了对查找器的方法调用并触发了它们的执行。 如果返回true,则可以依靠设置自定义存储库实现实例。
	 * 
	 */
	public class QueryExecutorMethodInterceptor implements MethodInterceptor {
		// 方法缓存。方法 -> RepositoryQuery
		private final Map<Method, RepositoryQuery> queries = new ConcurrentHashMap<Method, RepositoryQuery>();
		// 自定义实现类
		private final Object customImplementation;
 		// 附加repository特定信息
		private final RepositoryInformation repositoryInformation;
		// 简单的域服务,可将查询结果转换为专用类型
		private final QueryExecutionResultHandler resultHandler;
  		// 实际代理类
		private final Object target;

		/**
		 * 建立要在执行repository接口方法时调用的QueryMethod模型。
		 */
		public QueryExecutorMethodInterceptor(RepositoryInformation repositoryInformation, Object customImplementation,
				Object target, ProjectionFactory projectionFactory) {
			this.resultHandler = new QueryExecutionResultHandler();
			this.repositoryInformation = repositoryInformation;
			this.customImplementation = customImplementation;
			this.target = target;
			// 获取lookupStrategy(查找策略)
			QueryLookupStrategy lookupStrategy = getQueryLookupStrategy(queryLookupStrategyKey,
					RepositoryFactorySupport.this.evaluationContextProvider);
			lookupStrategy = lookupStrategy == null ? getQueryLookupStrategy(queryLookupStrategyKey) : lookupStrategy;
			Iterable<Method> queryMethods = repositoryInformation.getQueryMethods();

			if (lookupStrategy == null) {

				if (queryMethods.iterator().hasNext()) {
					throw new IllegalStateException("You have defined query method in the repository but "
							+ "you don't have any query lookup strategy defined. The "
							+ "infrastructure apparently does not support query methods!");
				}

				return;
			}

			for (Method method : queryMethods) {
				// 根据lookupStrategy(查找策略)查询RepositoryQuery
				RepositoryQuery query = lookupStrategy.resolveQuery(method, repositoryInformation, projectionFactory,
						namedQueries);
				// 为其添加监听
				invokeListeners(query);
				// 缓存。方法及其对应的RepositoryQuery
				queries.put(method, query);
			}
		}

		@SuppressWarnings({ "rawtypes", "unchecked" })
		private void invokeListeners(RepositoryQuery query) {

			for (QueryCreationListener listener : queryPostProcessors) {
				Class<?> typeArgument = GenericTypeResolver.resolveTypeArgument(listener.getClass(),
						QueryCreationListener.class);
				if (typeArgument != null && typeArgument.isAssignableFrom(query.getClass())) {
					listener.onCreation(query);
				}
			}
		}

		public Object invoke(MethodInvocation invocation) throws Throwable {

			Object result = doInvoke(invocation);

			return resultHandler.postProcessInvocationResult(result, invocation.getMethod());
		}

		private Object doInvoke(MethodInvocation invocation) throws Throwable {

			Method method = invocation.getMethod();
			Object[] arguments = invocation.getArguments();

			if (isCustomMethodInvocation(invocation)) {
				Method actualMethod = repositoryInformation.getTargetClassMethod(method);
				return executeMethodOn(customImplementation, actualMethod, arguments);
			}

			if (hasQueryFor(method)) {
				// 执行repository中自定义的方法
				return queries.get(method).execute(arguments);
			}

			// Lookup actual method as it might be redeclared in the interface
			// and we have to use the repository instance nevertheless
			Method actualMethod = repositoryInformation.getTargetClassMethod(method);
			return executeMethodOn(target, actualMethod, arguments);
		}


		private Object executeMethodOn(Object target, Method method, Object[] parameters) throws Throwable {

			try {
				return method.invoke(target, parameters);
			} catch (Exception e) {
				ClassUtils.unwrapReflectionException(e);
			}

			throw new IllegalStateException("Should not occur!");
		}

		private boolean hasQueryFor(Method method) {
			return queries.containsKey(method);
		}

		private boolean isCustomMethodInvocation(MethodInvocation invocation) {
			if (null == customImplementation) {
				return false;
			}

			return repositoryInformation.isCustomMethod(invocation.getMethod());
		}
	}