在上一篇文章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的配置是通过RepositoryConfigurationDelegate类组装实现的,这里面就包含了寻找Repository接口的子类(这里其实是子接口),并将其通过BeanDefinitionBuilder创建一个Bean实例注册到Bean Factory中,该Bean实例就是UserRepository的真实实现了。
下面我们先看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继承自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接口子类的集合。
再回到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;
}
}
以上这些步骤就是通过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();
}
}
}
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的创建步骤