Android Gradle:依赖下载

前言

 implementation 'org.greenrobot:eventbus:3.0.0'

  
  
  • 1

前面一章介绍了通过implementation 添加依赖的执行过程,在build 阶段的时候gradle 就会下载对应的额依赖。本章主要研究依赖的下载过程。

一 下载依赖

Configuration 有一个resolve 方法。

    /**
     * Resolves this configuration. This locates and downloads the files which make up this configuration, and returns
     * the resulting set of files.
     *
     * @return The files of this configuration.
     */
    Set<File> resolve();

有英文注释可以知道,这个方法会定位并且下载对应的文件。

    public Set<File> resolve() {
        return getFiles();
    }

    public Set<File> getFiles() {
        return intrinsicFiles.getFiles();
    }

其中的intrinsicFiles 为ConfigurationFileCollection,在DefaultConfiguration 的构造方法里面初始化的。

ConfigurationFileCollection.java

        public Set<File> getFiles() {
            ResolvedFilesCollectingVisitor visitor = new ResolvedFilesCollectingVisitor();
            getSelectedArtifacts().visitArtifacts(visitor, lenient);

            if (!lenient) {
                rethrowFailure("files", visitor.getFailures());
            }

            return visitor.getFiles();
        }

getSelectedArtifacts 主要是获取当前Configuration 需要依赖的项。

implementation 'org.greenrobot:eventbus:+'

如果我们使用上面的写法,也就是没有使用具体的版本号,此时getSelectedArtifacts也会访问网络获取的这个依赖的最新版本。
如果存在依赖冲突问题getSelectedArtifacts方法内部可能会抛出异常。

        private SelectedArtifactSet getSelectedArtifacts() {
            if (selectedArtifacts == null) {
                assertResolvingAllowed();
                resolveToStateOrLater(ARTIFACTS_RESOLVED);
                selectedArtifacts = cachedResolverResults.getVisitedArtifacts().select(dependencySpec, viewAttributes, componentSpec, allowNoMatchingVariants);
            }
            return selectedArtifacts;
        }

    private void resolveToStateOrLater(InternalState requestedState) {
        assertResolvingAllowed();
        synchronized (resolutionLock) {
            if (requestedState == GRAPH_RESOLVED || requestedState == ARTIFACTS_RESOLVED) {
            	//走这里
                resolveGraphIfRequired(requestedState);
            }
            if (requestedState == ARTIFACTS_RESOLVED) {
                resolveArtifactsIfRequired();
            }
        }
    }


    private void resolveGraphIfRequired(final InternalState requestedState) {
        //代码有删减
		 resolver.resolveGraph(DefaultConfiguration.this, cachedResolverResults);
    }

此处的resolver 是DefaultConfigurationResolver

public void resolveGraph(ConfigurationInternal configuration, ResolverResults results) {
	//代码有删减
    resolver.resolve(configuration, resolutionAwareRepositories, metadataHandler, Specs.<DependencyMetadata>satisfyAll(), graphVisitor, artifactsVisitor, attributesSchema, artifactTypeRegistry);

}

这个resolver 是  DefaultArtifactDependencyResolver

    public void resolve(ResolveContext resolveContext, List<? extends ResolutionAwareRepository> repositories, GlobalDependencyResolutionRules metadataHandler, Spec<? super DependencyMetadata> edgeFilter, DependencyGraphVisitor graphVisitor, DependencyArtifactsVisitor artifactsVisitor, AttributesSchemaInternal consumerSchema, ArtifactTypeRegistry artifactTypeRegistry) {
        LOGGER.debug("Resolving {}", resolveContext);
        ComponentResolversChain resolvers = createResolvers(resolveContext, repositories, metadataHandler, artifactTypeRegistry);
        DependencyGraphBuilder builder = createDependencyGraphBuilder(resolvers, resolveContext.getResolutionStrategy(), metadataHandler, edgeFilter, consumerSchema, moduleIdentifierFactory, moduleExclusions, buildOperationExecutor);

        DependencyGraphVisitor artifactsGraphVisitor = new ResolvedArtifactsGraphVisitor(artifactsVisitor, resolvers.getArtifactSelector(), moduleExclusions);

        // Resolve the dependency graph
        builder.resolve(resolveContext, new CompositeDependencyGraphVisitor(graphVisitor, artifactsGraphVisitor));
    }

在这里插入图片描述
assembleResult 内部会遍历所有需要下载的依赖然后执行visitEdges方法

ResolvedArtifactsGraphVisitor.java

    @Override
    public void visitEdges(DependencyGraphNode node) {
        for (DependencyGraphEdge dependency : node.getIncomingEdges()) {
            DependencyGraphNode parent = dependency.getFrom();
            //这是关键
            ArtifactsForNode artifacts = getArtifacts(dependency, node);
            artifactResults.visitArtifacts(parent, node, artifacts.artifactSetId, artifacts.artifactSet);
        }
        for (LocalFileDependencyMetadata fileDependency : node.getOutgoingFileEdges()) {
            int id = nextId++;
            artifactResults.visitArtifacts(node, fileDependency, id, artifactSelector.resolveArtifacts(fileDependency));
        }
    }

在这里插入图片描述
exclusions 应该就是在implementation 方法传递的过滤规则,这里没去仔细看过。

DefaultArtifactSelector.java
在这里插入图片描述
在这里插入图片描述

RepositoryChainArtifactResolver chain 记录的是在setting.gradle 里面配置的所有仓库。
在这里插入图片描述

可以看到是先在缓存里面查询,缓存不存在就去远程获取。
sourceRepository.getRemoteAccess()用于获取访问网络访问器,resolveArtifacts(unpackedComponent, result)用于获取依赖。

这里以RemoteRepositoryAccess 为例。由名字就知道RemoteRepositoryAccess 可以获取远程数据。

        @Override
        public void resolveArtifact(ComponentArtifactMetadata artifact, ModuleSource moduleSource, BuildableArtifactResolveResult result) {
            ExternalResourceResolver.this.resolveArtifact(artifact, moduleSource, result);
        }

ExternalResourceResolver.java

    protected void resolveArtifact(ComponentArtifactMetadata componentArtifact, ModuleSource moduleSource, BuildableArtifactResolveResult result) {
        ModuleComponentArtifactMetadata artifact = (ModuleComponentArtifactMetadata) componentArtifact;

        File localFile;
        try {
            localFile = download(artifact, moduleSource, result);
        } catch (Throwable e) {
            result.failed(new ArtifactResolveException(artifact.getId(), e));
            return;
        }

        if (localFile != null) {
            result.resolved(localFile);
        } else {
            result.notFound(artifact.getId());
        }
    }

    protected File download(ModuleComponentArtifactMetadata artifact, ModuleSource moduleSource, BuildableArtifactResolveResult result) {
        LocallyAvailableExternalResource artifactResource = createArtifactResolver(moduleSource).resolveArtifact(artifact, result);
        if (artifactResource == null) {
            return null;
        }

        return artifactResource.getFile();
    }

createArtifactResolver 返回的是DefaultExternalResourceArtifactResolver

    public LocallyAvailableExternalResource resolveArtifact(ModuleComponentArtifactMetadata artifact, ResourceAwareResolveResult result) {
        if (artifact instanceof ModuleDescriptorArtifactMetadata) {
            return downloadStaticResource(ivyPatterns, artifact, result);
        }
        return downloadStaticResource(artifactPatterns, artifact, result);
    }


    private LocallyAvailableExternalResource downloadStaticResource(List<ResourcePattern> patternList, final ModuleComponentArtifactMetadata artifact, ResourceAwareResolveResult result) {
        for (ResourcePattern resourcePattern : patternList) {
        	//获取需要下载的依赖
            ExternalResourceName location = resourcePattern.getLocation(artifact);
            result.attempted(location);
            LOGGER.debug("Loading {}", location);
            LocallyAvailableResourceCandidates localCandidates = locallyAvailableResourceFinder.findCandidates(artifact);
            try {
                LocallyAvailableExternalResource resource = resourceAccessor.getResource(location, new CacheAwareExternalResourceAccessor.ResourceFileStore() {
                    public LocallyAvailableResource moveIntoCache(File downloadedResource) {
                        return fileStore.move(artifact.getId(), downloadedResource);
                    }
                }, localCandidates);
                if (resource != null) {
                    return resource;
                }
            } catch (Exception e) {
                throw ResourceExceptions.getFailed(location.getUri(), e);
            }
        }
        return null;
    }

ExternalResourceName location 表示需要下载的来,resourceAccessor是CacheAwareExternalResourceAccessor,有名字可以直到,resourceAccessor会优先在缓存里面查找对应的依赖。如果缓存里面不存在,那么会DefaultExternalResourceRepository 的resource 方法下载资源。最终通过AccessorBackedExternalResource 的withContentIfPresent下载对应的依赖。

    private LocallyAvailableExternalResource copyToCache(final ExternalResourceName source, final ResourceFileStore fileStore, final ExternalResource resource) {
        // Download to temporary location
        DownloadAction downloadAction = new DownloadAction(source);
        try {
           //resource 是AccessorBackedExternalResource  的代理类
            resource.withContentIfPresent(downloadAction);
        } catch (Exception e) {
            throw ResourceExceptions.getFailed(source.getUri(), e);
        }
        if (downloadAction.metaData == null) {
            return null;
        }

        // Move into cache
        try {
            return moveIntoCache(source, downloadAction.destination, fileStore, downloadAction.metaData);
        } finally {
            downloadAction.destination.delete();
        }
    }

    @Nullable
    @Override
    public <T> ExternalResourceReadResult<T> withContentIfPresent(Transformer<? extends T, ? super InputStream> transformer) throws ResourceException {
        try {
        	//accessor
            ExternalResourceReadResponse response = accessor.openResource(name.getUri(), revalidate);
            if (response == null) {
                return null;
            }
            try {
                CountingInputStream input = new CountingInputStream(new BufferedInputStream(response.openStream()));
                try {
                    T value = transformer.transform(input);
                    return ExternalResourceReadResult.of(input.getCount(), value);
                } finally {
                    input.close();
                }
            } finally {
                response.close();
            }
        } catch (IOException e) {
            throw ResourceExceptions.getFailed(name.getUri(), e);
        }
    }

accessor 为HttpResourceAccessor,此时通过HttpResourceAccessor 打开网络连接,获取的输入流。

    @Override
    @Nullable
    public HttpResponseResource openResource(final URI uri, boolean revalidate) {
        String location = uri.toString();
        LOGGER.debug("Constructing external resource: {}", location);

        HttpClientResponse response = http.performGet(location, revalidate);
        if (response != null) {
            return wrapResponse(uri, response);
        }

        return null;
    }

http 为HttpClientHelper,HttpClientHelper 内部通过HttpClient 访问网络,关于Gradle 访问网络这一块就接收到这。

二、产物

前面介绍了Gradle 下载依赖的过程,可以知道Gradle 最终使用的是HttpClinet 网络框架下载的依赖文件,但是依赖文件下载之后还并不可以直接使用,例如 implementation ‘org.greenrobot:eventbus:3.0.0’ 下载下来是个aar文件,但android 最终需要的是包含源码的jar 文件,因此这里就需要解压等操作。这一步的操作名为Transform ,经过Transform 之后的文件我们称之为产物,也是我们最终最终依赖的文件。

        public Set<File> getFiles() {
            ResolvedFilesCollectingVisitor visitor = new ResolvedFilesCollectingVisitor();
            getSelectedArtifacts().visitArtifacts(visitor, lenient);

            if (!lenient) {
                rethrowFailure("files", visitor.getFailures());
            }

            return visitor.getFiles();
        }

        private SelectedArtifactSet getSelectedArtifacts() {
            if (selectedArtifacts == null) {
                assertResolvingAllowed();
                resolveToStateOrLater(ARTIFACTS_RESOLVED);
                selectedArtifacts = cachedResolverResults.getVisitedArtifacts().select(dependencySpec, viewAttributes, componentSpec, allowNoMatchingVariants);
            }
            return selectedArtifacts;
        }

    private void resolveToStateOrLater(InternalState requestedState) {
        assertResolvingAllowed();
        synchronized (resolutionLock) {
            if (requestedState == GRAPH_RESOLVED || requestedState == ARTIFACTS_RESOLVED) {
                resolveGraphIfRequired(requestedState);
            }
            if (requestedState == ARTIFACTS_RESOLVED) {
                resolveArtifactsIfRequired();
            }
        }
    }

resolveGraphIfRequired 是下载对应的依赖,这个在前面介绍了,resolveArtifactsIfRequired 会遍历下载的依赖文件然后进行转换。

    private void resolveArtifactsIfRequired() {
        if (resolvedState == ARTIFACTS_RESOLVED) {
            return;
        }
        if (resolvedState != GRAPH_RESOLVED) {
            throw new IllegalStateException("Cannot resolve artifacts before graph has been resolved.");
        }
        resolver.resolveArtifacts(DefaultConfiguration.this, cachedResolverResults);
        resolvedState = ARTIFACTS_RESOLVED;
    }

    public void resolveArtifacts(ConfigurationInternal configuration, ResolverResults results) {
        ArtifactResolveState resolveState = (ArtifactResolveState) results.getArtifactResolveState();
        ResolvedGraphResults graphResults = resolveState.graphResults;
        VisitedArtifactsResults artifactResults = resolveState.artifactsResults;
        TransientConfigurationResultsBuilder transientConfigurationResultsBuilder = resolveState.transientConfigurationResultsBuilder;

        TransientConfigurationResultsLoader transientConfigurationResultsFactory = new TransientConfigurationResultsLoader(transientConfigurationResultsBuilder, graphResults);

        DefaultLenientConfiguration result = new DefaultLenientConfiguration(configuration, resolveState.failures, artifactResults, resolveState.fileDependencyResults, transientConfigurationResultsFactory, artifactTransforms, buildOperationExecutor);
        results.artifactsResolved(new DefaultResolvedConfiguration(result), result);
    }

results 与下面截图中的cachedResolverResults是同一个对象。
results.artifactsResolved 仅仅是保存一些变量。

    @Override
    public void artifactsResolved(ResolvedConfiguration resolvedConfiguration, VisitedArtifactSet visitedArtifacts) {
        this.resolvedConfiguration = resolvedConfiguration;
        this.visitedArtifacts = visitedArtifacts;
        this.artifactResolveState = null;
    }


此处需要知道的是VisitedArtifactSet visitedArtifacts实际是DefaultLenientConfiguration

图一
在调用完resolveToStateOrLater之后会接着调用cachedResolverResults.getVisitedArtifacts().select 方法。其中cachedResolverResults.getVisitedArtifacts() 返回的就是上面创建的DefaultLenientConfiguration 对象。
下面接着看DefaultLenientConfiguration 的select 方法

    @Override
    public SelectedArtifactSet select(final Spec<? super Dependency> dependencySpec, final AttributeContainerInternal requestedAttributes, final Spec<? super ComponentIdentifier> componentSpec, boolean allowNoMatchingVariants) {
        final SelectedArtifactResults artifactResults;
        //
        VariantSelector selector = artifactTransforms.variantSelector(requestedAttributes, allowNoMatchingVariants);
        artifactResults = this.artifactResults.select(componentSpec, selector);

        return new SelectedArtifactSet() {//代码有删减};
    }

这里面的artifactTransforms 用来产物转换,例如android插件内的AarTransform.
这个值是在构造DefaultConfigurationResolver确定的。其实际类型是DefaultArtifactTransforms。

artifactTransforms.variantSelector 返回AttributeMatchingVariantSelector 类型的一个变量,而this.artifactResults.select(componentSpec, selector)内部会调用AttributeMatchingVariantSelector 的select方法。

        @Override
        public ResolvedArtifactSet select(ResolvedVariantSet producer) {
            try {
                return doSelect(producer);
            } catch (Throwable t) {
                return new BrokenResolvedArtifactSet(t);
            }
        }

        private ResolvedArtifactSet doSelect(ResolvedVariantSet producer) {
            AttributeMatcher matcher = schema.withProducer(producer.getSchema());
            List<? extends ResolvedVariant> matches = matcher.matches(producer.getVariants(), requested);
		
            List<Pair<ResolvedVariant, ConsumerVariantMatchResult.ConsumerVariant>> candidates = new ArrayList<Pair<ResolvedVariant, ConsumerVariantMatchResult.ConsumerVariant>>();
            for (ResolvedVariant variant : producer.getVariants()) {
                AttributeContainerInternal variantAttributes = variant.getAttributes().asImmutable();
                ConsumerVariantMatchResult matchResult = new ConsumerVariantMatchResult();
                //这个是核心
                matchingCache.collectConsumerVariants(variantAttributes, requested, matchResult);
                for (ConsumerVariantMatchResult.ConsumerVariant consumerVariant : matchResult.getMatches()) {
                    candidates.add(Pair.of(variant, consumerVariant));
                }
            }
            if (candidates.size() == 1) {
                Pair<ResolvedVariant, ConsumerVariantMatchResult.ConsumerVariant> result = candidates.get(0);
                return new ConsumerProvidedResolvedVariant(result.getLeft().getArtifacts(), result.getRight().attributes, result.getRight().transformer);
            }

      

        }
    }

我们接着进入VariantAttributeMatchingCache 的collectConsumerVariants 方法

    public void collectConsumerVariants(AttributeContainerInternal actual, AttributeContainerInternal requested, ConsumerVariantMatchResult result) {
        AttributeSpecificCache toCache = getCache(requested);
        ConsumerVariantMatchResult cachedResult = toCache.transforms.get(actual);
        if (cachedResult == null) {
            cachedResult = new ConsumerVariantMatchResult();
            findProducersFor(actual, requested, cachedResult);
            toCache.transforms.put(actual, cachedResult);
        }
        cachedResult.applyTo(result);
    }

图片
variantTransforms 里面保存的应该就是用户注册的转换器。

图片
inputVariant.transformer.transform(file) 就会执行用户注册的转换器。下面我们以android 的ExtractAarTransform为例,ExtractAarTransform 主要是解压aar文件。

      override fun transform(outputs: TransformOutputs) {
        recordArtifactTransformSpan(
            parameters.projectName.get(),
            GradleTransformExecutionType.EXTRACT_AAR_ARTIFACT_TRANSFORM
        ) {
            val inputFile = primaryInput.get().asFile
            val name = Files.getNameWithoutExtension(inputFile.name)
            val outputDir = outputs.dir(name)
            FileUtils.mkdirs(outputDir)
            val aarExtractor = AarExtractor()
            aarExtractor.extract(inputFile, outputDir)
            val classesJar = File(File(outputDir, FD_JARS), FN_CLASSES_JAR)
            if (!classesJar.exists()) {
                try {
                    Files.createParentDirs(classesJar)
                    FileOutputStream(classesJar).use { out ->
                        // FileOutputStream above is the actual OS resource that will get closed,
                        // JarOutputStream writes the bytes or an empty jar in it.
                        val jarOutputStream = JarOutputStream(BufferedOutputStream(out), Manifest())
                        jarOutputStream.close()
                    }
                } catch (e: IOException) {
                    throw RuntimeException("Cannot create missing classes.jar", e)
                }
            }
        }
    }

AarExtractor 的extract 方法会将aar 文件解压到指定的文件夹。android 插件里面还有一个AarTransform ,有感兴趣的可以自己看看。

总结

本文的内容到此就结束了,本篇主要粗略的介绍了一下Gradle 是如何下载依赖文件以及下载之后的转换操作,其实这对于我们的实际开发没什么作用,当初之所以看这一块主要是我想看看Gradle 是使用的什么网络框架。

转载:https://blog.csdn.net/qq_31469589/article/details/117414197

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值