背景
在上一篇文章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的創建步驟
- 獲取自定義的Repository接口並以BeanDefinition的形式呈現
- 將接口定義封裝爲RepositoryConfiguration
- 再轉換爲BeanDefinitionBuilder,從而創建JpaRepositoryFactoryBean實例
- 通過FactoryBean創建JpaRepositoryFactory實例
- 生成Repository接口的代理SimpleJpaRepository
自下而上,從左到右查看類圖的走向,就是前面所述的流程。