Spring Data之Repository創建及源碼分析

背景

在上一篇文章Spring Data之EntityManager創建及源碼分析介紹了EntityManager的創建過程,我們使用Spring Data JPA開發時一般是通過自定義一個例如UserRepository的接口,然後繼承JpaRepository或者CrudRepository、PagingAndSortingRepository從而獲得一系列默認的CURD方法。

public interface UserRepository extends JpaRepository<User,Long> {
}
@Autowired
private UserRepository userRepository;
    
public void queryAll() {
    List<User> users = userRepository.findAll();
    log.info("result:{}",users);
}

我們知道接口是不能被實例化的,但通過@Autowired private UserRepository userRepository就能使用userRepository實例的方法進行持久化操作。UserRepository接口是在什麼時候被誰實現的呢,跟EntityManager又是如何結合在一起的呢?@Autowired注入的對象又是誰呢?這篇文章就來進行分析。

Repository創建

通過上一篇文章我們知道,Repository的配置是通過RepositoryConfigurationDelegate類組裝實現的,這裏面就包含了尋找Repository接口的子類(這裏其實是子接口),並將其通過BeanDefinitionBuilder創建一個Bean實例註冊到Bean Factory中,該Bean實例就是UserRepository的真實實現了。

RepositoryConfigurationDelegate

下面我們先看RepositoryConfigurationDelegate的registerRepositoriesIn方法

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<>();

	//獲取RepositoryConfiguration的集合
	for (RepositoryConfiguration<? extends RepositoryConfigurationSource> configuration : extension
			.getRepositoryConfigurations(configurationSource, resourceLoader, inMultiStoreMode)) {

		//將configuration轉換爲BeanDefinitionBuilder
		BeanDefinitionBuilder definitionBuilder = builder.build(configuration);

		//給definitionBuilder指定若干屬性的賦值,包含entityManager
		extension.postProcess(definitionBuilder, configurationSource);

		if (isXml) {
			extension.postProcess(definitionBuilder, (XmlRepositoryConfigurationSource) configurationSource);
		} else {
			extension.postProcess(definitionBuilder, (AnnotationRepositoryConfigurationSource) configurationSource);
		}

		AbstractBeanDefinition beanDefinition = definitionBuilder.getBeanDefinition();
		//獲取註冊Bean的名稱,也就是UserRepository接口實際對象的Bean名稱
		String beanName = configurationSource.generateBeanName(beanDefinition);

		if (LOGGER.isDebugEnabled()) {
			LOGGER.debug(REPOSITORY_REGISTRATION, extension.getModuleName(), beanName,
					configuration.getRepositoryInterface(), configuration.getRepositoryFactoryBeanClassName());
		}

		beanDefinition.setAttribute(FACTORY_BEAN_OBJECT_TYPE, configuration.getRepositoryInterface());

		//註冊定義好的Bean,即在Application Context中創建該Bean的實例
		registry.registerBeanDefinition(beanName, beanDefinition);
		definitions.add(new BeanComponentDefinition(beanDefinition, beanName));
	}

	return definitions;
}

其中for裏面的extension.getRepositoryConfigurations是關鍵,該方法就是尋找UserRepository的地方,具體實現如下

public abstract class RepositoryConfigurationExtensionSupport implements RepositoryConfigurationExtension {
	
	public <T extends RepositoryConfigurationSource> Collection<RepositoryConfiguration<T>> getRepositoryConfigurations(
			T configSource, ResourceLoader loader, boolean strictMatchesOnly) {

		Assert.notNull(configSource, "ConfigSource must not be null!");
		Assert.notNull(loader, "Loader must not be null!");

		Set<RepositoryConfiguration<T>> result = new HashSet<>();

		//獲取Repository接口子類的Bean定義
		for (BeanDefinition candidate : configSource.getCandidates(loader)) {

			RepositoryConfiguration<T> configuration = getRepositoryConfiguration(candidate, configSource);
			Class<?> repositoryInterface = loadRepositoryInterface(configuration,
					getConfigurationInspectionClassLoader(loader));

			if (repositoryInterface == null) {
				result.add(configuration);
				continue;
			}

			RepositoryMetadata metadata = AbstractRepositoryMetadata.getMetadata(repositoryInterface);

			if (!useRepositoryConfiguration(metadata)) {
				continue;
			}

			if (!strictMatchesOnly || configSource.usesExplicitFilters()) {
				result.add(configuration);
				continue;
			}

			if (isStrictRepositoryCandidate(metadata)) {
				result.add(configuration);
			}
		}

		return result;
	}
}

getCandidates的實現

public abstract class RepositoryConfigurationSourceSupport implements RepositoryConfigurationSource {
	@Override
	public Streamable<BeanDefinition> getCandidates(ResourceLoader loader) {

		//定義了一個scanner指定需要包含的類型
		RepositoryComponentProvider scanner = new RepositoryComponentProvider(getIncludeFilters(), registry);
		scanner.setConsiderNestedRepositoryInterfaces(shouldConsiderNestedRepositories());
		scanner.setEnvironment(environment);
		scanner.setResourceLoader(loader);

		getExcludeFilters().forEach(it -> scanner.addExcludeFilter(it));

		//根據掃描的包路徑,查找需要的BeanDefinition,也就是UserRepository
		return Streamable.of(() -> getBasePackages().stream()//
				.flatMap(it -> scanner.findCandidateComponents(it).stream()));
	}
}

RepositoryComponentProvider

RepositoryComponentProvider繼承自ClassPathScanningCandidateComponentProvider,可以看到super.addIncludeFilter加入了Repository.class,這就是前面一直說的Repository接口。

class RepositoryComponentProvider extends ClassPathScanningCandidateComponentProvider {
	public RepositoryComponentProvider(Iterable<? extends TypeFilter> includeFilters, BeanDefinitionRegistry registry) {

		super(false);

		Assert.notNull(includeFilters, "Include filters must not be null!");
		Assert.notNull(registry, "BeanDefinitionRegistry must not be null!");

		this.registry = registry;

		if (includeFilters.iterator().hasNext()) {
			for (TypeFilter filter : includeFilters) {
				addIncludeFilter(filter);
			}
		} else {
			super.addIncludeFilter(new InterfaceTypeFilter(Repository.class));
			super.addIncludeFilter(new AnnotationTypeFilter(RepositoryDefinition.class, true, true));
		}

		addExcludeFilter(new AnnotationTypeFilter(NoRepositoryBean.class));
	}
	//根據包路徑查找符合規則的BeanDefinition
	@Override
	public Set<BeanDefinition> findCandidateComponents(String basePackage) {

		Set<BeanDefinition> candidates = super.findCandidateComponents(basePackage);

		for (BeanDefinition candidate : candidates) {
			if (candidate instanceof AnnotatedBeanDefinition) {
				AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
			}
		}

		return candidates;
	}
}

通過ClassPathScanningCandidateComponentProvider的findCandidateComponents方法獲取符合條件的BeanDefinition集合,在這裏就是Repository接口子類的集合。

RepositoryBeanDefinitionBuilder

再回到RepositoryConfigurationDelegate的registerRepositoriesIn方法,獲取到RepositoryConfiguration後,使用RepositoryBeanDefinitionBuilder的build方法將其轉換爲BeanDefinitionBuilder

class RepositoryBeanDefinitionBuilder {
	//將RepositoryConfiguration轉換爲BeanDefinitionBuilder
	public BeanDefinitionBuilder build(RepositoryConfiguration<?> configuration) {

		Assert.notNull(registry, "BeanDefinitionRegistry must not be null!");
		Assert.notNull(resourceLoader, "ResourceLoader must not be null!");

		//實際創建的是JpaRepositoryFactoryBean
		//這是在@EnableJpaRepositories註解中默認指定的
		BeanDefinitionBuilder builder = BeanDefinitionBuilder
				.rootBeanDefinition(configuration.getRepositoryFactoryBeanClassName());

		builder.getRawBeanDefinition().setSource(configuration.getSource());
		builder.addConstructorArgValue(configuration.getRepositoryInterface());
		builder.addPropertyValue("queryLookupStrategyKey", configuration.getQueryLookupStrategyKey());
		builder.addPropertyValue("lazyInit", configuration.isLazyInit());

		configuration.getRepositoryBaseClassName()//
				.ifPresent(it -> builder.addPropertyValue("repositoryBaseClass", it));

		NamedQueriesBeanDefinitionBuilder definitionBuilder = new NamedQueriesBeanDefinitionBuilder(
				extension.getDefaultNamedQueryLocation());
		configuration.getNamedQueriesLocation().ifPresent(definitionBuilder::setLocations);

		builder.addPropertyValue("namedQueries", definitionBuilder.build(configuration.getSource()));

		registerCustomImplementation(configuration).ifPresent(it -> {
			builder.addPropertyReference("customImplementation", it);
			builder.addDependsOn(it);
		});

		BeanDefinitionBuilder fragmentsBuilder = BeanDefinitionBuilder
				.rootBeanDefinition(RepositoryFragmentsFactoryBean.class);

		List<String> fragmentBeanNames = registerRepositoryFragmentsImplementation(configuration) //
				.map(RepositoryFragmentConfiguration::getFragmentBeanName) //
				.collect(Collectors.toList());

		fragmentsBuilder.addConstructorArgValue(fragmentBeanNames);

		builder.addPropertyValue("repositoryFragments",
				ParsingUtils.getSourceBeanDefinition(fragmentsBuilder, configuration.getSource()));

		RootBeanDefinition evaluationContextProviderDefinition = new RootBeanDefinition(
				ExtensionAwareEvaluationContextProvider.class);
		evaluationContextProviderDefinition.setSource(configuration.getSource());

		builder.addPropertyValue("evaluationContextProvider", evaluationContextProviderDefinition);

		return builder;
	}
}

JpaRepositoryFactoryBean

以上這些步驟就是通過BeanDefinitionBuilder構建出了JpaRepositoryFactoryBean,它的父類繼承了InitializingBean,它實現了afterPropertiesSet方法,所以在實例化JpaRepositoryFactoryBean後,調用會進入到afterPropertiesSet方法

public class JpaRepositoryFactoryBean<T extends Repository<S, ID>, S, ID>
		extends TransactionalRepositoryFactoryBeanSupport<T, S, ID> {
	
	@Override
	protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) {
		return new JpaRepositoryFactory(entityManager);
	}
	
	@Override
	public void afterPropertiesSet() {

		Assert.state(entityManager != null,"EntityManager must not be null!");
		super.afterPropertiesSet();
	}
}

進而我們找到父類的afterPropertiesSet定義

public abstract class RepositoryFactoryBeanSupport<T extends Repository<S, ID>, S, ID>
		implements InitializingBean, RepositoryFactoryInformation<S, ID>, FactoryBean<T>, BeanClassLoaderAware,
		BeanFactoryAware, ApplicationEventPublisherAware {
	
	public void afterPropertiesSet() {
		//調用子類的實現,返回的是JpaRepositoryFactory
		this.factory = createRepositoryFactory();
		this.factory.setQueryLookupStrategyKey(queryLookupStrategyKey);
		this.factory.setNamedQueries(namedQueries);
		this.factory.setEvaluationContextProvider(evaluationContextProvider);
		this.factory.setBeanClassLoader(classLoader);
		this.factory.setBeanFactory(beanFactory);

		if (publisher != null) {
			this.factory.addRepositoryProxyPostProcessor(new EventPublishingRepositoryProxyPostProcessor(publisher));
		}

		repositoryBaseClass.ifPresent(this.factory::setRepositoryBaseClass);

		RepositoryFragments customImplementationFragment = customImplementation //
				.map(RepositoryFragments::just) //
				.orElseGet(RepositoryFragments::empty);

		RepositoryFragments repositoryFragmentsToUse = this.repositoryFragments //
				.orElseGet(RepositoryFragments::empty) //
				.append(customImplementationFragment);

		this.repositoryMetadata = this.factory.getRepositoryMetadata(repositoryInterface);
		//獲取Repository的代理實現,即UserRepository的代理
		this.repository = Lazy.of(() -> this.factory.getRepository(repositoryInterface, repositoryFragmentsToUse));

		if (!lazyInit) {
			this.repository.get();
		}
	}
}

RepositoryFactorySupport

JpaRepositoryFactory的父類

/**
 1. 用於創建給定的Repotory的接口代理實現
*/
public abstract class RepositoryFactorySupport implements BeanClassLoaderAware, BeanFactoryAware {
	
	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!");

		//Repository的元數據,包含接口類型、主鍵類型、實體類型
		RepositoryMetadata metadata = getRepositoryMetadata(repositoryInterface);
		RepositoryComposition composition = getRepositoryComposition(metadata, fragments);
		RepositoryInformation information = getRepositoryInformation(metadata, composition);

		validate(information, composition);

		Object target = getTargetRepository(information);

		//創建UserRepository的代理,SimpleJpaRepository
		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);
	}
}

調試可以看到,代理接口是UserRepository,代理類是SimpleJpaRepository
在這裏插入圖片描述
在實際使用userRepository的地方,可以看到它是一個Proxy,tatgetSource是SimpleJpaRepository@5652,與上一步創建的代理對象是同一個。
在這裏插入圖片描述
SimpleJpaRepository實際是對EntityManager調用的各種封裝

結束

總結一下Repository的創建步驟

  1. 獲取自定義的Repository接口並以BeanDefinition的形式呈現
  2. 將接口定義封裝爲RepositoryConfiguration
  3. 再轉換爲BeanDefinitionBuilder,從而創建JpaRepositoryFactoryBean實例
  4. 通過FactoryBean創建JpaRepositoryFactory實例
  5. 生成Repository接口的代理SimpleJpaRepository

自下而上,從左到右查看類圖的走向,就是前面所述的流程。
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章