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
Spring Data之Repository创建及源码分析_第1张图片
在实际使用userRepository的地方,可以看到它是一个Proxy,tatgetSource是SimpleJpaRepository@5652,与上一步创建的代理对象是同一个。
Spring Data之Repository创建及源码分析_第2张图片
SimpleJpaRepository实际是对EntityManager调用的各种封装

结束

总结一下Repository的创建步骤

  1. 获取自定义的Repository接口并以BeanDefinition的形式呈现
  2. 将接口定义封装为RepositoryConfiguration
  3. 再转换为BeanDefinitionBuilder,从而创建JpaRepositoryFactoryBean实例
  4. 通过FactoryBean创建JpaRepositoryFactory实例
  5. 生成Repository接口的代理SimpleJpaRepository

自下而上,从左到右查看类图的走向,就是前面所述的流程。
Spring Data之Repository创建及源码分析_第3张图片

你可能感兴趣的:(Spring,Data)