Repository 是怎么从接⼝变成 Bean 的

一、Repository Bean 是如何创建的

1、JpaRepositoriesRegistrar

a、激活了 @EnableJpaRepositories(主类上的注解)
b、返回了 JpaRepositoryConfigExtension(扩展)

2、RepositoryBeanDefifinitionRegistrarSupport.registerBeanDefifinitions JpaRepositoriesRegistrar的父类

a、  注册 Repository Bean (类型是 JpaRepositoryFactoryBean
 
3、RepositoryConfifigurationExtensionSupport.getRepositoryConfifigurations
a 、取得 Repository 配置
4、JpaRepositoryFactory.getTargetRepository
a、取得Repository的bean
以下是JpaRepositoriesRegistrar(作用是为基于 JPA 的 repository 接口动态地创建 repository bean 定义。)
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package org.springframework.data.jpa.repository.config;

import java.lang.annotation.Annotation;
import org.springframework.data.repository.config.RepositoryBeanDefinitionRegistrarSupport;
import org.springframework.data.repository.config.RepositoryConfigurationExtension;

class JpaRepositoriesRegistrar extends RepositoryBeanDefinitionRegistrarSupport {
    JpaRepositoriesRegistrar() {
    }

    protected Class<? extends Annotation> getAnnotation() {
        return EnableJpaRepositories.class;//告诉它是@EnableJpaRepositories这个注解
    }

    protected RepositoryConfigurationExtension getExtension() {//扩展
        return new JpaRepositoryConfigExtension();
    }
}
以下是RepositoryBeanDefinitionRegistararSupport(用于为 repository 接口动态地 创建 bean 定义。)
//省略了一些代码,只显示关键代码
package org.springframework.data.repository.config;

public abstract class RepositoryBeanDefinitionRegistrarSupport implements ImportBeanDefinitionRegistrar, ResourceLoaderAware, EnvironmentAware {

    public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry registry) {//主要是一些配置信息
        Assert.notNull(annotationMetadata, "AnnotationMetadata must not be null!");
        Assert.notNull(registry, "BeanDefinitionRegistry must not be null!");
        Assert.notNull(this.resourceLoader, "ResourceLoader must not be null!");
        if (annotationMetadata.getAnnotationAttributes(this.getAnnotation().getName()) != null) {
            AnnotationRepositoryConfigurationSource configurationSource = new AnnotationRepositoryConfigurationSource(annotationMetadata, this.getAnnotation(), this.resourceLoader, this.environment, registry);
            RepositoryConfigurationExtension extension = this.getExtension();
            RepositoryConfigurationUtils.exposeRegistration(extension, registry, configurationSource);
            RepositoryConfigurationDelegate delegate = new RepositoryConfigurationDelegate(configurationSource, this.resourceLoader, this.environment);
            delegate.registerRepositoriesIn(registry, extension);//调用此方法进行注册Repository
        }
    }

}

以下是registerRepositoriesIn方法(用于注册 repository bean 定义。)

​
    public List<BeanComponentDefinition> registerRepositoriesIn(BeanDefinitionRegistry registry, RepositoryConfigurationExtension extension) {
        if (LOG.isInfoEnabled()) {
            LOG.info("Bootstrapping Spring Data repositories in {} mode.", this.configurationSource.getBootstrapMode().name());
        }

        extension.registerBeansForRoot(registry, this.configurationSource);
//定义一个builder
        RepositoryBeanDefinitionBuilder builder = new RepositoryBeanDefinitionBuilder(registry, extension, this.configurationSource, this.resourceLoader, this.environment);
//将Repository接口一个一个拉出来
        List<BeanComponentDefinition> definitions = new ArrayList();
        StopWatch watch = new StopWatch();
        if (LOG.isDebugEnabled()) {
            LOG.debug("Scanning for repositories in packages {}.", this.configurationSource.getBasePackages().stream().collect(Collectors.joining(", ")));
        }

        watch.start();
        Collection<RepositoryConfiguration<RepositoryConfigurationSource>> configurations = extension.getRepositoryConfigurations(this.configurationSource, this.resourceLoader, this.inMultiStoreMode);
        Map<String, RepositoryConfiguration<?>> configurationsByRepositoryName = new HashMap(configurations.size());
        Iterator var8 = configurations.iterator();
//然后一个一个地为他们进行beanDefinitions的定义
        while(var8.hasNext()) {
            RepositoryConfiguration<? extends RepositoryConfigurationSource> configuration = (RepositoryConfiguration)var8.next();
            configurationsByRepositoryName.put(configuration.getRepositoryInterface(), configuration);
//用build进行了创建
            BeanDefinitionBuilder definitionBuilder = builder.build(configuration);
            extension.postProcess(definitionBuilder, this.configurationSource);
            if (this.isXml) {
                extension.postProcess(definitionBuilder, (XmlRepositoryConfigurationSource)this.configurationSource);
            } else {
                extension.postProcess(definitionBuilder, (AnnotationRepositoryConfigurationSource)this.configurationSource);
            }

            AbstractBeanDefinition beanDefinition = definitionBuilder.getBeanDefinition();
            String beanName = this.configurationSource.generateBeanName(beanDefinition);
            if (LOG.isTraceEnabled()) {
                LOG.trace("Spring Data {} - Registering repository: {} - Interface: {} - Factory: {}", new Object[]{extension.getModuleName(), beanName, configuration.getRepositoryInterface(), configuration.getRepositoryFactoryBeanClassName()});
            }

            beanDefinition.setAttribute("factoryBeanObjectType", configuration.getRepositoryInterface());
//把bean的属性放进去
            registry.registerBeanDefinition(beanName, beanDefinition);
            definitions.add(new BeanComponentDefinition(beanDefinition, beanName));
        }

        potentiallyLazifyRepositories(configurationsByRepositoryName, registry, this.configurationSource.getBootstrapMode());
        watch.stop();
        if (LOG.isInfoEnabled()) {
            LOG.info("Finished Spring Data repository scanning in {}ms. Found {} repository interfaces.", watch.getLastTaskTimeMillis(), configurations.size());
        }

        return definitions;
    }

​

以下是build方法(构建 repository bean 定义。)

    public BeanDefinitionBuilder build(RepositoryConfiguration<?> configuration) {
        Assert.notNull(this.registry, "BeanDefinitionRegistry must not be null!");
        Assert.notNull(this.resourceLoader, "ResourceLoader must not be null!");
//取得类名
        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());
        builder.setLazyInit(configuration.isLazyInit());
        configuration.getRepositoryBaseClassName().ifPresent((it) -> {
            builder.addPropertyValue("repositoryBaseClass", it);
        });
        NamedQueriesBeanDefinitionBuilder definitionBuilder = new NamedQueriesBeanDefinitionBuilder(this.extension.getDefaultNamedQueryLocation());
        configuration.getNamedQueriesLocation().ifPresent(definitionBuilder::setLocations);
        builder.addPropertyValue("namedQueries", definitionBuilder.build(configuration.getSource()));
        this.registerCustomImplementation(configuration).ifPresent((it) -> {
            builder.addPropertyReference("customImplementation", it);
            builder.addDependsOn(it);
        });
        BeanDefinitionBuilder fragmentsBuilder = BeanDefinitionBuilder.rootBeanDefinition(RepositoryFragmentsFactoryBean.class);
        List<String> fragmentBeanNames = (List)this.registerRepositoryFragmentsImplementation(configuration).map(RepositoryFragmentConfiguration::getFragmentBeanName).collect(Collectors.toList());
        fragmentsBuilder.addConstructorArgValue(fragmentBeanNames);
        builder.addPropertyValue("repositoryFragments", ParsingUtils.getSourceBeanDefinition(fragmentsBuilder, configuration.getSource()));
        return builder;
    }

 以下是JpaRepositoryConfigExtension(用于为 JPA repository 提供配置支持。)

//以下非完整代码

package org.springframework.data.jpa.repository.config;

//扩展
public class JpaRepositoryConfigExtension extends RepositoryConfigurationExtensionSupport {
    private static final Class<?> PAB_POST_PROCESSOR = PersistenceAnnotationBeanPostProcessor.class;
    private static final String DEFAULT_TRANSACTION_MANAGER_BEAN_NAME = "transactionManager";
    private static final String ENABLE_DEFAULT_TRANSACTIONS_ATTRIBUTE = "enableDefaultTransactions";
    private static final String JPA_METAMODEL_CACHE_CLEANUP_CLASSNAME = "org.springframework.data.jpa.util.JpaMetamodelCacheCleanup";

    public JpaRepositoryConfigExtension() {
    }

    public String getModuleName() {
        return "JPA";
    }

    public String getRepositoryFactoryBeanClassName() {
        return JpaRepositoryFactoryBean.class.getName();//获得我要注册的bean的类型
    }

以下是JpaRepositoryFactoryBean(是 Spring Data JPA 提供的一个工厂 bean,用于创建 JPA repository 的实例。)

//非全部代码

public class JpaRepositoryFactoryBean<T extends Repository<S, ID>, S, ID> extends TransactionalRepositoryFactoryBeanSupport<T, S, ID> {
   //创建一个JpaRepositoryFactory,再在里面创建一个Repository
//所有操作执行完后调用afterPropertiesSet方法
    public void afterPropertiesSet() {
        Assert.state(this.entityManager != null, "EntityManager must not be null!");
        super.afterPropertiesSet();
    }
}

以下是afterPropertiesSet方法(用于在所有 bean 属性被设置后,执行一些必要的初始化工作。)

    public void afterPropertiesSet() {
//仅展示主要代码
        this.repository = Lazy.of(() -> {
            return (Repository)this.factory.getRepository(this.repositoryInterface, repositoryFragmentsToUse);//创建对应的Repository的代理对象
        });
        if (!this.lazyInit) {
            this.repository.get();
        }

    }

二、接⼝中的⽅法是如何被解释的(自己在接口中定义的方法是怎么回事)

1、为RepositoryFactorySupport.getRepository 添加了Advice( RepositoryFactorySupport 用于创建 repository 实例。它的 getRepository 方法用于获取指定 repository 接口的实例。)
A、DefaultMethodInvokingMethodInterceptor
B、QueryExecutorMethodInterceptor(查询)
 
a、在AbstractJpaQuery.execute 中执⾏具体的查询
b、语法解析(...find...by...)在 Part 中  
以下是RepositoryFactorySupport的getRepository方法
//getRepository 方法用于获取指定 repository 接口的实例
    public <T> T getRepository(Class<T> repositoryInterface, RepositoryComposition.RepositoryFragments fragments) {
        if (LOG.isDebugEnabled()) {
            LOG.debug("Initializing repository instance for {}…", repositoryInterface.getName());
        }

        Assert.notNull(repositoryInterface, "Repository interface must not be null!");
        Assert.notNull(fragments, "RepositoryFragments must not be null!");
        RepositoryMetadata metadata = this.getRepositoryMetadata(repositoryInterface);
        RepositoryComposition composition = this.getRepositoryComposition(metadata, fragments);
        RepositoryInformation information = this.getRepositoryInformation(metadata, composition);
        this.validate(information, composition);
        Object target = this.getTargetRepository(information);
        ProxyFactory result = new ProxyFactory();
        result.setTarget(target);
        result.setInterfaces(new Class[]{repositoryInterface, Repository.class, TransactionalProxy.class});
        if (MethodInvocationValidator.supports(repositoryInterface)) {
            result.addAdvice(new MethodInvocationValidator());
        }
//添加了Advice,在创建 repository 实例时添加额外的逻辑
        result.addAdvice(SurroundingTransactionDetectorMethodInterceptor.INSTANCE);
        result.addAdvisor(ExposeInvocationInterceptor.ADVISOR);
        this.postProcessors.forEach((processor) -> {
            processor.postProcess(result, information);
        });
        result.addAdvice(new DefaultMethodInvokingMethodInterceptor());
        ProjectionFactory projectionFactory = this.getProjectionFactory(this.classLoader, this.beanFactory);
//创建了QueryExecutorMethodInterceptor的一个拦截
        result.addAdvice(new QueryExecutorMethodInterceptor(information, projectionFactory));
        composition = composition.append(RepositoryFragment.implemented(target));
        result.addAdvice(new ImplementationMethodExecutionInterceptor(composition));
        T repository = result.getProxy(this.classLoader);
        if (LOG.isDebugEnabled()) {
            LOG.debug("Finished creation of repository instance for {}.", repositoryInterface.getName());
        }

        return repository;
    }

以下是QueryExecutorMethodInterceptor里面的invoke(拦截器会根据方法的注解或参数类型等信息,确定当前方法需要执行的操作类型,例如查询、更新或删除等。)

  @Nullable
        public Object invoke(MethodInvocation invocation) throws Throwable {
            Method method = invocation.getMethod();//取得方法
            return QueryExecutionConverters.getExecutionAdapter(method.getReturnType()).apply(() -> {
                return this.resultHandler.postProcessInvocationResult(this.doInvoke(invocation), method);
            });//到doInvoke
        }

以下是QueryExecutorMethodInterceptor里面的doinvoke

    @Nullable
        private Object doInvoke(MethodInvocation invocation) throws Throwable {
            Method method = invocation.getMethod();
            Object[] arguments = invocation.getArguments();
            return this.hasQueryFor(method) ? ((RepositoryQuery)this.queries/*查询*/.get(method)).execute/*执行*/(arguments) : invocation.proceed();
        }

语法解析(Part文件)

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一点知趣

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值